Linux内核中VLAN的实现过程(8)-Netlink控制接口(vlan基于端口)

网友投稿 548 2022-10-12


Linux内核中VLAN的实现过程(8)-Netlink控制接口(vlan基于端口)

Linux内核中VLAN的实现过程(8)

本节主要关注和解析vlan netlink控制接口的实现,代码位于net/8021q/vlan_netlink.c文件中。Netlink主要用于在内核和用户空间进程之间传输信息。

VLAN设备Netlink初始化

配置和注册新设备

static int vlan_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[], struct netlink_ext_ack *extack) { // vlan设备私有数据 struct vlan_dev_priv *vlan = vlan_dev_priv(dev); struct net_device *real_dev; unsigned int max_mtu; __be16 proto; int err; // 校验netlink属性:vlan id if (!data[IFLA_VLAN_ID]) { NL_SET_ERR_MSG_MOD(extack, "VLAN id not specified"); return -EINVAL; } // 验证是否指定了接口索引 if (!tb[IFLA_LINK]) { NL_SET_ERR_MSG_MOD(extack, "link not specified"); return -EINVAL; } // 根据指定的接口索引(nla_get_u32(tb[IFLA_LINK]))查找宿主设备 real_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK])); if (!real_dev) { NL_SET_ERR_MSG_MOD(extack, "link does not exist"); return -ENODEV; } // 校验netlink属性:vlan协议 if (data[IFLA_VLAN_PROTOCOL]) proto = nla_get_be16(data[IFLA_VLAN_PROTOCOL]); else // 未指定,则默认802.1q协议 proto = htons(ETH_P_8021Q); // 初始化vlan设备私有数据 vlan->vlan_proto = proto; vlan->vlan_id = nla_get_u16(data[IFLA_VLAN_ID]); vlan->real_dev = real_dev; dev->priv_flags |= (real_dev->priv_flags & IFF_XMIT_DST_RELEASE); vlan->flags = VLAN_FLAG_REORDER_HDR; // 从宿主设备vlan组中查找符合vlan协议和vlan id的设备,并校验,extract是为ack的error消息 err = vlan_check_real_dev(real_dev, vlan->vlan_proto, vlan->vlan_id, extack); if (err < 0) return err; // 计算最大mtu max_mtu = netif_reduces_vlan_mtu(real_dev) ? real_dev->mtu - VLAN_HLEN : real_dev->mtu; // 没有指定mtu,则使用上面计算的mtu if (!tb[IFLA_MTU]) dev->mtu = max_mtu; // 校验:vlan设备mtu不可能大于宿主设备的最大mtu else if (dev->mtu > max_mtu) return -EINVAL; // 修vlan设备参数 err = vlan_changelink(dev, tb, data, extack); if (err) return err; // 注册vlan设备 err = register_vlan_dev(dev, extack); if (err) vlan_dev_free_egress_priority(dev); return err; }

修改已存在设备参数

static int vlan_changelink(struct net_device *dev, struct nlattr *tb[], struct nlattr *data[], struct netlink_ext_ack *extack) { struct ifla_vlan_flags *flags; struct ifla_vlan_qos_mapping *m; struct nlattr *attr; int rem, err; // 判断vlan flags是否设置 if (data[IFLA_VLAN_FLAGS]) { // 获取vlan flags flags = nla_data(data[IFLA_VLAN_FLAGS]); // 修改vlan flags err = vlan_dev_change_flags(dev, flags->flags, flags->mask); if (err) return err; } // 判断入口qos是否设置 if (data[IFLA_VLAN_INGRESS_QOS]) { // 遍历嵌套的qos属性 nla_for_each_nested(attr, data[IFLA_VLAN_INGRESS_QOS], rem) { // 属性payload m = nla_data(attr); // 设置入口优先级 vlan_dev_set_ingress_priority(dev, m->to, m->from); } } // 判断出口qos是否设置 if (data[IFLA_VLAN_EGRESS_QOS]) { // 遍历嵌套的qos属性 nla_for_each_nested(attr, data[IFLA_VLAN_EGRESS_QOS], rem) { // 属性payload m = nla_data(attr); // 设置出口优先级 err = vlan_dev_set_egress_priority(dev, m->from, m->to); if (err) return err; } } return 0; }

删除设备

void unregister_vlan_dev(struct net_device *dev, struct list_head *head) { struct vlan_dev_priv *vlan = vlan_dev_priv(dev); struct net_device *real_dev = vlan->real_dev; struct vlan_info *vlan_info; struct vlan_group *grp; u16 vlan_id = vlan->vlan_id; ASSERT_RTNL(); // 获取vlan设备信息 vlan_info = rtnl_dereference(real_dev->vlan_info); BUG_ON(!vlan_info); // 获取设备上的vlan组 grp = &vlan_info->grp; // vlan个数减1 grp->nr_vlan_devs--; // 注销garp vlan协议和multiple vlan协议 if (vlan->flags & VLAN_FLAG_MVRP) vlan_mvrp_request_leave(dev); if (vlan->flags & VLAN_FLAG_GVRP) vlan_gvrp_request_leave(dev); // 从vlan组中移除该vlan设备 vlan_group_set_device(grp, vlan->vlan_proto, vlan_id, NULL); // 从宿主设备上删除指向vlan设备的链接,调用者必须持有RTNL锁 netdev_upper_dev_unlink(real_dev, dev); // 此函数关闭设备接口并将其从内核表中删除。 如果head不为NULL,则设备将排队等待稍后取消注册。调用者必须持有rtnl信号量。 /* Because unregister_netdevice_queue() makes sure at least one rcu * grace period is respected before device freeing, * we dont need to call synchronize_net() here. */ unregister_netdevice_queue(dev, head); // vlan个数为0 if (grp->nr_vlan_devs == 0) { // 注销宿主设备上的garp vlan和multiple vlan协议应用 vlan_mvrp_uninit_applicant(real_dev); vlan_gvrp_uninit_applicant(real_dev); } // 删除宿主设备上记录的该vlan id设备 vlan_vid_del(real_dev, vlan->vlan_proto, vlan_id); }


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java面试题冲刺第十二天
下一篇:迁移/home分区
相关文章

 发表评论

暂时没有评论,来抢沙发吧~