/* 不支持PFMEMALLOC置位 */ if (pfmemalloc && !skb_pfmemalloc_protocol(skb)) goto drop;
/* 如果是vlan数据 */ if (skb_vlan_tag_present(skb)) { if (pt_prev) { ret = deliver_skb(skb, pt_prev, orig_dev); pt_prev = NULL; } if (vlan_do_receive(&skb)) goto another_round; elseif (unlikely(!skb)) goto unlock; }
/* 如果注册了handle,如bridge */ rx_handler = rcu_dereference(skb->dev->rx_handler); if (rx_handler) { if (pt_prev) { ret = deliver_skb(skb, pt_prev, orig_dev); pt_prev = NULL; } switch (rx_handler(&skb)) { /* 被rx_handler处理,不用在处理 */ case RX_HANDLER_CONSUMED: ret = NET_RX_SUCCESS; goto unlock;
/* 重新走一轮,skb->dev被rx_handler修改了 */ case RX_HANDLER_ANOTHER: goto another_round;
/* 精确传递:ptype->dev == skb->dev */ case RX_HANDLER_EXACT: deliver_exact = true; /* 什么都不做,就像没有调用rx_handler一样传递skb */ case RX_HANDLER_PASS: break; default: BUG(); } }
/* 还有VLAN,上面没有找到对应vlan的设备 */ if (unlikely(skb_vlan_tag_present(skb))) {
/* 如果获取到vid,则将pkt_type设置为PACKET_OTHERHOST * PACKET_OTHERHOST:该帧目的地址不属于与该接口相匹配的地址,如果开启转发则转发, * 否则丢弃。vlan_tci值为0。 */ if (skb_vlan_tag_get_id(skb)) skb->pkt_type = PACKET_OTHERHOST; /* Note: we might in the future use prio bits * and set skb->priority like in vlan_do_receive() * For the time being, just ignore Priority Code Point */ skb->vlan_tci = 0; }
if (pt_prev) { if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC))) goto drop; else /* 向上层传递 */ ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev); } else { drop: /* 统计网卡丢弃的数据包数 */ atomic_long_inc(&skb->dev->rx_dropped); kfree_skb(skb); /* Jamal, now you will not able to escape explaining * me how you were going to use this. :-) */ ret = NET_RX_DROP; }