Linux内核实践 - 如何添加网络协议[二]:实现
发布时间:2016-10-08 04:45:51 所属栏目: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;
}
(编辑:宣城站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


