标签:
/* * The rps_sock_flow_table contains mappings of flows to the last CPU * on which they were processed by the application (set in recvmsg). */ struct rps_sock_flow_table { unsigned int mask; u16 ents[0]; }; #define RPS_SOCK_FLOW_TABLE_SIZE(_num) (sizeof(struct rps_sock_flow_table) + \ ((_num) * sizeof(u16)))
/* * The rps_dev_flow structure contains the mapping of a flow to a CPU, the * tail pointer for that CPU‘s input queue at the time of last enqueue, and * a hardware filter index. */ struct rps_dev_flow { u16 cpu; //此链路上次使用的cpu u16 filter; unsigned int last_qtail; //此设备队列入队的sk_buff的个数 }; #define RPS_NO_FILTER 0xffff /* * The rps_dev_flow_table structure contains a table of flow mappings. */ struct rps_dev_flow_table { unsigned int mask; struct rcu_head rcu; struct rps_dev_flow flows[0]; //实现hash表 }; #define RPS_DEV_FLOW_TABLE_SIZE(_num) (sizeof(struct rps_dev_flow_table) + \ ((_num) * sizeof(struct rps_dev_flow)))
int inet_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t size, int flags) { struct sock *sk = sock->sk; int addr_len = 0; int err; sock_rps_record_flow(sk); //设置CPU id err = sk->sk_prot->recvmsg(iocb, sk, msg, size, flags & MSG_DONTWAIT, flags & ~MSG_DONTWAIT, &addr_len); if (err >= 0) msg->msg_namelen = addr_len; return err; } EXPORT_SYMBOL(inet_recvmsg);
3117 hash = skb_get_hash(skb); 3118 if (!hash) 3119 goto done; 3120 3121 flow_table = rcu_dereference(rxqueue->rps_flow_table); //设备队列的hash表 3122 sock_flow_table = rcu_dereference(rps_sock_flow_table); //全局的hash表 3123 if (flow_table && sock_flow_table) { 3124 u16 next_cpu; 3125 struct rps_dev_flow *rflow; 3126 3127 rflow = &flow_table->flows[hash & flow_table->mask]; 3128 tcpu = rflow->cpu; 3129 3130 next_cpu = sock_flow_table->ents[hash & sock_flow_table->mask]; //得到用户程序运行的CPU id 3131 3132 /* 3133 * If the desired CPU (where last recvmsg was done) is 3134 * different from current CPU (one in the rx-queue flow 3135 * table entry), switch if one of the following holds: 3136 * - Current CPU is unset (equal to RPS_NO_CPU). 3137 * - Current CPU is offline. 3138 * - The current CPU‘s queue tail has advanced beyond the 3139 * last packet that was enqueued using this table entry. 3140 * This guarantees that all previous packets for the flow 3141 * have been dequeued, thus preserving in order delivery. 3142 */ 3143 if (unlikely(tcpu != next_cpu) && 3144 (tcpu == RPS_NO_CPU || !cpu_online(tcpu) || 3145 ((int)(per_cpu(softnet_data, tcpu).input_queue_head - 3146 rflow->last_qtail)) >= 0)) { 3147 tcpu = next_cpu; 3148 rflow = set_rps_cpu(dev, skb, rflow, next_cpu); 3149 } 3150 3151 if (tcpu != RPS_NO_CPU && cpu_online(tcpu)) { 3152 *rflowp = rflow; 3153 cpu = tcpu; 3154 goto done; 3155 } 3156 }
2374 #ifdef CONFIG_RPS 2375 /* Elements below can be accessed between CPUs for RPS */ 2376 struct call_single_data csd ____cacheline_aligned_in_smp; 2377 struct softnet_data *rps_ipi_next; 2378 unsigned int cpu; 2379 unsigned int input_queue_head; //队列头,也可以理解为出队的位置 2380 unsigned int input_queue_tail; //队列尾,也可以理解为入队的位置 2381 #endif
标签:
原文地址:http://www.cnblogs.com/lxgeek/p/4182364.html