多平台统一管理软件接口,如何实现多平台统一管理软件接口
367
2022-10-14
Linux VLAN透传
一、 Linux对VLAN数据的处理(1)VLAN初始化static struct packet_type vlan_packet_type __read_mostly = {.type =cpu_to_be16(ETH_P_8021Q),.func = vlan_skb_recv, /*VLAN receive method */}; vlan_proto_init调用dev_add_pack(&vlan_packet_type)函数进行VLAN的注册,把ETH_P_8021Q 处理函数挂在ptype_base下,即数据接收的VLAN的入口函数为vlan_skb_recv (2)VLAN数据处理 内核中的vlan模块就是工作在协议栈里,通过注册dev_add_pack注册了8021Q的协议类型,netif_receive_skb->__netif_receive_skb遍历所有的协议类型时发现了它,于是进入了vlan的接收函数vlan_skb_recv(vlan_dev.c),这个函数里剥离vlan层,重置以太网层的proto,重新调用netif_rx进入真正的协议栈处理流程。对于Linux,无论什么数据包通过网卡驱动后都会进入__netif_receive_skb函数。该函数中对VLAN的处理如下:static int__netif_receive_skb(struct sk_buff *skb){ … … //遍历ptye_all链表 list_for_each_entry_rcu(ptype, &ptype_all,list) { if (ptype->dev == null_or_orig || ptype->dev ==skb->dev || ptype->dev ==orig_dev) { if (pt_prev) ret = deliver_skb(skb, pt_prev, orig_dev); pt_prev = ptype; } } … … // bridge逻辑 /* Handle special case of bridge or macvlan */ 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; } skb = rx_handler(skb); if (!skb) goto out; } … … //遍历ptype_base type = skb->protocol; //如果是VLAN,则这里type被置为VLAN协议,即0x8100(经过VLAN处理后,protocol会被重置) list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & PTYPE_HASH_MASK],list) { if (ptype->type == type && (ptype->dev ==null_or_orig || ptype->dev ==skb->dev || ptype->dev == orig_dev || ptype->dev ==orig_or_bond)) { if (pt_prev){ // deliver_skb函数最终调用paket_type.func(),如果是VLAN,由于type为802.1Q的协议,所以会调用其对应的协议处理函数:vlan_skb_recv ret = deliver_skb(skb, pt_prev, orig_dev);} pt_prev = ptype; } } … …} 二、 vlan_skb_recv函数解析定义几个vlan接口和vlan ID相关的宏:#define MTC_STP_PACKET_VLAN_ID 4094#define MTC_WAN_VLAN_ID 2#define MTC_LAN_VLAN_ID 1#define MTC_WAN_IFNAME "eth2.2"#define MTC_LAN_IFNAME "eth2.1" int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device*orig_dev){… … // 从skb解析出对应的vlan_idvhdr = (struct vlan_hdr*)skb->data;vlan_tci =ntohs(vhdr->h_vlan_TCI);vlan_id = vlan_tci &VLAN_VID_MASK; … … //这里dev指向的是真实的dev,通过__find_vlan_dev函数根据vlan_id找到对应接口的dev(比如现在用的系统真实dev接口名称为eth2; vlan_id==1的接口名称为eth2.1; vlan_id==2的接口名称为eth2.2)vlan_dev =__find_vlan_dev(dev, vlan_id); //以下处理是为了确保vlan_id为非1和非2的时候数据包不会被丢掉#ifdef PRODUCT_MT7628STPAP_MTC/*There is not any device attachto the MTC_STP_PACKET_VLAN_ID(4094) vlan id,In order to pass the normalprocessing of vlan_skb_recv function,we set the vlan_dev toMTC_WAN_IFNAME(eth2.2).by wwk,20170426*/if(MTC_STP_PACKET_VLAN_ID ==vlan_id_back) { vlan_dev = __dev_get_by_name(&init_net,MTC_LAN_IFNAME);} #endif /* If the VLAN device isdefined, we use it. * If not, and the VID is 0, it is a 802.1ppacket (not * really a VLAN), so we will just netif_rx itlater to the * original interface, but with the skb->protoset to the * wrapped proto: we do nothing here. */if (!vlan_dev) { if (vlan_id) { pr_debug("%s:ERROR: No net_device for VID: %u on dev: %s\n", __func__, vlan_id, dev->name); //如果通过上面的函数__find_vlan_dev没找到vlan_dev,则把数据包扔掉,当前系统默认仅支持MTC_WAN_IFNAME和MTC_LAN_IFNAME,即VLAN ID为2和VLAN ID为1的VLAN goto err_unlock; } else { … …}} else { … …} //以下为对从WAN进来的包进行处理:从WAN进来的包copy一份同步发到LAN端,发送之前把把vlan_id设置为4096#ifdef PRODUCT_MT7628STPAP_MTC/*if pkg from vlanMTC_WAN_VLAN_ID, then forward one copy to MTC_LAN_IFNAME(vlan_id isMTC_STP_PACKET_VLAN_ID)
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~