当内核收到了一个网络包
之前两篇文章给这篇做了铺垫,分别讲了。
从网线到网卡 


从网卡到内存 


注册硬中断处理程序 
request_irq(netdev->irq, &e1000_intr, ...);
硬中断 e1000_intr 干了什么 
// 注册的硬中断处理函数
static irqreturn_t e1000_intr(int irq, void *data, struct pt_regs *regs) {
__netif_rx_schedule(netdev);
}
include\linux\netdevice.h
static inline void __netif_rx_schedule(struct net_device *dev) {
list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list);
// 发出软中断
__raise_softirq_irqoff(NET_RX_SOFTIRQ);
}

注册软中断处理程序 
static int __init net_dev_init(void) {
    open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL);
    open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL);
}
// transmit 发送
static void net_tx_action(struct softirq_action *h) {...}
// receive 接收
static void net_rx_action(struct softirq_action *h) {...}

软中断 net_rx_action 干了什么 
static void net_rx_action(struct softirq_action *h) {
    struct softnet_data *queue = &__get_cpu_var(softnet_data);   
    while (!list_empty(&queue->poll_list)) {
        struct net_device dev = list_entry(
            queue->poll_list.next, struct net_device, poll_list);
        dev->poll(dev, &budget);
    }
}
netdev->poll = &e1000_clean;
static int e1000_clean(struct net_device *netdev, int *budget) {
    struct e1000_adapter *adapter = netdev->priv;    
    e1000_clean_tx_irq(adapter);
    e1000_clean_rx_irq(adapter, &work_done, work_to_do);
}
// drivers\net\e1000\e1000_main.c
e1000_clean_rx_irq(struct e1000_adapter *adapter) {
    ...
    netif_receive_skb(skb);
    ...
}
// net\core\dev.c
int netif_receive_skb(struct sk_buff *skb) {
    ...
    list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) {
        ...
        deliver_skb(skb, ptype, 0);
        ...
    }
    ...
}
static __inline__ int deliver_skb(
        struct sk_buff *skb, struct packet_type *pt_prev, int last) {
    ...
    return pt_prev->func(skb, skb->dev, pt_prev);
}
协议栈的注册 
// net\ipv4\ip_output.c
static struct packet_type ip_packet_type = {
    .type = __constant_htons(ETH_P_IP),
    .func = ip_rcv,
};
void __init ip_init(void) {
    dev_add_pack(&ip_packet_type);
}
// net\core\dev.c
void dev_add_pack(struct packet_type *pt) {
    if (pt->type == htons(ETH_P_ALL)) {
        list_add_rcu(&pt->list, &ptype_all);
    } else {
        hash = ntohs(pt->type) & 15;
        list_add_rcu(&pt->list, &ptype_base[hash]);
    }
}
module_init(inet_init);
static struct inet_protocol tcp_protocol = {
    .handler =  tcp_v4_rcv,
    .err_handler =  tcp_v4_err,
    .no_policy =    1,
};
static struct inet_protocol udp_protocol = {
    .handler =  udp_rcv,
    .err_handler =  udp_err,
    .no_policy =    1,
};
static int __init inet_init(void) {
    inet_add_protocol(&udp_protocol, IPPROTO_UDP);
    inet_add_protocol(&tcp_protocol, IPPROTO_TCP);
    ip_init();
    tcp_init();
}
网络层处理函数 ip_rcv 干了什么 
// net\ipv4\ip_input.c
int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) {
    ...
    return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
               ip_rcv_finish);
}
static inline int ip_rcv_finish(struct sk_buff *skb) {
    ...
    if (skb->dst == NULL) {
        if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))
            goto drop; 
    }
    ...
    return dst_input(skb);
}
// include\net\dst.h
// rth->u.dst.input= ip_local_deliver;
static inline int dst_input(struct sk_buff *skb) {
    ...
    skb->dst->input(skb);
    ...
}
// net\ipv4\ip_input.c
int ip_local_deliver(struct sk_buff *skb) {
    ...
    return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
               ip_local_deliver_finish);
}
static inline int ip_local_deliver_finish(struct sk_buff *skb) {
    ...
    ipprot = inet_protos[hash];
    ipprot->handler(skb);
    ...
}
static struct inet_protocol tcp_protocol = {
    .handler =  tcp_v4_rcv,
    .err_handler =  tcp_v4_err,
    .no_policy =    1,
};
static struct inet_protocol udp_protocol = {
    .handler =  udp_rcv,
    .err_handler =  udp_err,
    .no_policy =    1,
};

评论
