Kernel: 4.12.6
每个cpu都有自己的softnet_data结构,用来处理数据包接收,但是当softnet_data所在cpu无法工作时,即CPUHP_NET_DEV_DEAD状态,就需要将工作转交给其他cpu处理;
1 static int dev_cpu_dead(unsigned int oldcpu) 2 { 3 struct sk_buff **list_skb; 4 struct sk_buff *skb; 5 unsigned int cpu; 6 struct softnet_data *sd, *oldsd, *remsd = NULL; 7 8 //禁用本地中断 9 local_irq_disable(); 10 //获取当前cpu 11 cpu = smp_processor_id(); 12 //找到sd 13 sd = &per_cpu(softnet_data, cpu); 14 //原sd 15 oldsd = &per_cpu(softnet_data, oldcpu); 16 17 /* Find end of our completion_queue. */ 18 //找到当前cpu完成队列尾部 19 list_skb = &sd->completion_queue; 20 while (*list_skb) 21 list_skb = &(*list_skb)->next; 22 /* Append completion queue from offline CPU. */ 23 //将旧cpu队列连接到当前cpu队列尾部 24 *list_skb = oldsd->completion_queue; 25 oldsd->completion_queue = NULL; 26 27 /* Append output queue from offline CPU. */ 28 //将旧cpu的outputqueue挂到当前cpu尾部 29 if (oldsd->output_queue) { 30 *sd->output_queue_tailp = oldsd->output_queue; 31 sd->output_queue_tailp = oldsd->output_queue_tailp; 32 oldsd->output_queue = NULL; 33 oldsd->output_queue_tailp = &oldsd->output_queue; 34 } 35 /* Append NAPI poll list from offline CPU, with one exception : 36 * process_backlog() must be called by cpu owning percpu backlog. 37 * We properly handle process_queue & input_pkt_queue later. 38 */ 39 //将napi poll list挂到当前cpu poll list尾部 40 while (!list_empty(&oldsd->poll_list)) { 41 struct napi_struct *napi = list_first_entry(&oldsd->poll_list, 42 struct napi_struct, 43 poll_list); 44 45 list_del_init(&napi->poll_list); 46 if (napi->poll == process_backlog) 47 napi->state = 0; 48 else 49 ____napi_schedule(sd, napi); 50 } 51 52 //触发发送软中断 53 raise_softirq_irqoff(NET_TX_SOFTIRQ); 54 55 //启用中断 56 local_irq_enable(); 57 58 #ifdef CONFIG_RPS 59 remsd = oldsd->rps_ipi_list; 60 oldsd->rps_ipi_list = NULL; 61 #endif 62 /* send out pending IPI‘s on offline CPU */ 63 net_rps_send_ipi(remsd); 64 65 /* Process offline CPU‘s input_pkt_queue */ 66 //把process_queue和input_queue中的skb添加到当前cpu的backlog中 67 while ((skb = __skb_dequeue(&oldsd->process_queue))) { 68 netif_rx_ni(skb); 69 input_queue_head_incr(oldsd); 70 } 71 while ((skb = skb_dequeue(&oldsd->input_pkt_queue))) { 72 netif_rx_ni(skb); 73 input_queue_head_incr(oldsd); 74 } 75 76 return 0; 77 }
时间: 2024-10-17 21:39:49