Linux内核实践 - 如何添加网络协议[二]:实现
发布时间:2016-10-08 04:50:34 所属栏目:Linux 来源:站长网
导读:副标题#e# 内核版本:2.6.34 实现思路: 报文在网络协议栈中的流动,对于接收来讲,是 对报文的脱壳的过程,由于报文是已知的输入,只要逐个解析协议号;对于发送来讲,是各层发送函数的嵌套调用,由于没有已 知的输入,只能按事先设计好的协议进行层层构造
在接收函数brcm_skb_rcv()中对于成功接收的报文会增加流量统计: rx_stats = per_cpu_ptr(brcm_dev_info(skb->dev)->brcm_rx_stats, smp_processor_id()); rx_stats->rx_packets++; rx_stats->rx_bytes += skb->len; 在发送函数brcm_dev_hard_start_xmit()中对于发送的报文会增加相应流量 统计: if (likely(ret == NET_XMIT_SUCCESS)) { txq->tx_packets++; txq->tx_bytes += len; } else txq->tx_dropped++; 而brcm_netdev_ops->ndo_get_stats()即brcm_dev_get_stats()函数,则会将brcm网卡设 备中记录的发送和接收流量信息汇总成通用的格式net_device_stats,像ifconfig等命令使用的就是net_device_stats转换后的 结果。 完整收发函数 有了这些后接收函数brcm_skb_recv()就可以完整了,其中关于报头 brcm_hdr的处理可以略过,由于是空想的协议,含义是可以自己设定的: int brcm_skb_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *orig_dev) { struct brcm_hdr *bhdr; struct brcm_rx_stats *rx_stats; int op, brcm_port; skb = skb_share_check(skb, GFP_ATOMIC); if(!skb) goto err_free; bhdr = (struct brcm_hdr *)skb->data; op = bhdr->brcm_tag.brcm_53242_op; brcm_port = bhdr->brcm_tag.brcm_53242_src_portid- 23; rcu_read_lock(); // drop wrong brcm tag packet if (op != BRCM_RCV_OP || brcm_port < 1 || brcm_port > 27) goto err_unlock; skb->dev = find_brcm_dev(dev, brcm_port); if (!skb->dev) { goto err_unlock; } rx_stats = per_cpu_ptr(brcm_dev_info(skb->dev)->brcm_rx_stats, smp_processor_id()); rx_stats->rx_packets++; rx_stats->rx_bytes += skb->len; skb_pull_rcsum(skb, BRCM_HLEN); switch (skb->pkt_type) { case PACKET_BROADCAST: /* Yeah, stats collect these together.. */ /* stats->broadcast ++; // no such counter :-( */ break; case PACKET_MULTICAST: rx_stats->multicast++; break; case PACKET_OTHERHOST: /* Our lower layer thinks this is not local, let's make sure. * This allows the VLAN to have a different MAC than the * underlying device, and still route correctly. */ if (!compare_ether_addr(eth_hdr(skb)->h_dest, skb->dev->dev_addr)) skb->pkt_type = PACKET_HOST; break; default: break; } // set protocol skb->protocol = bhdr->brcm_encapsulated_proto; // reorder skb skb = brcm_check_reorder_header(skb); if (!skb) { rx_stats->rx_errors++; goto err_unlock; } netif_rx(skb); rcu_read_unlock(); return NET_RX_SUCCESS; err_unlock: rcu_read_unlock(); err_free: kfree_skb(skb); return NET_RX_DROP; } (编辑:淮北站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
站长推荐
热点阅读