首页 > 代码库 > 网络子系统87_veth实现

网络子系统87_veth实现

//使用veth
//1.创建两块虚拟网卡veth1、veth2,然后点对点连接,此后两块网卡的数据会互相发送到对方
$ ip link add veth1 type veth peer name veth2

//2.创建网络命名空间t1
$ ip netns add t1

//3.将veth0加入t1,此时veth0便看不到了,因为被加入到其他命名空间中了
$ ip link set veth0 netns t1

//4.配置veth0的ip地址
$ ip netns exec t1 ifconfig eth0 192.168.1.200/24

//5.设置t1网络的默认路由
$ ip netns exec t1 route add default gw 192.168.1.1

//6.此时将veth2加入本地网桥中,便可以实现veth1在t1中访问外部网络了,过程略,可参考docker中的网络配置步骤


//veth的实现方法(drivers/net/veth.c)
//向ip link注册服务
1.1 static __init int veth_init(void)
{
	return rtnl_link_register(&veth_link_ops);
}

//处理ip link命令
2.1 static struct rtnl_link_ops veth_link_ops = {
	.kind		= DRV_NAME,
	.priv_size	= sizeof(struct veth_priv),
	.setup		= veth_setup,
	.validate	= veth_validate,
	.newlink	= veth_newlink,
	.dellink	= veth_dellink,
	.policy		= veth_policy,
	.maxtype	= VETH_INFO_MAX,
};


//新加入一条veth链接
2.2 static int veth_newlink(struct net_device *dev,
			 struct nlattr *tb[], struct nlattr *data[])
{
	int err;
	struct net_device *peer;
	struct veth_priv *priv;
	char ifname[IFNAMSIZ];
	struct nlattr *peer_tb[IFLA_MAX + 1], **tbp;

	 //首先创建并注册peer
	if (data != NULL && data[VETH_INFO_PEER] != NULL) {
		struct nlattr *nla_peer;
		//解析命令行参数
		nla_peer = data[VETH_INFO_PEER];
		err = nla_parse(peer_tb, IFLA_MAX,
				nla_data(nla_peer) + sizeof(struct ifinfomsg),
				nla_len(nla_peer) - sizeof(struct ifinfomsg),
				ifla_policy);
		...
	} else
		tbp = tb;

	//初始化peer
	...

	//注册peer
	err = register_netdevice(peer);
	if (err < 0)
		goto err_register_peer;
	

	//初始化peer的对等端
	...

	//注册peer的对等端
	err = register_netdevice(dev);
	if (err < 0)
		goto err_register_dev;

	//互相将peer保存到private中,在xmit的时候使用
	priv = netdev_priv(dev);
	priv->peer = peer;

	priv = netdev_priv(peer);
	priv->peer = dev;
	return 0;

err_register_dev:
err_alloc_name:
	unregister_netdevice(peer);
	return err;

err_register_peer:
	free_netdev(peer);
	return err;
}


//初始化veth设备
2.3 static void veth_setup(struct net_device *dev)
{
	//以太网设备的通用初始化
	ether_setup(dev);

	//veth的操作列表
	dev->netdev_ops = &veth_netdev_ops;
	dev->ethtool_ops = &veth_ethtool_ops;
	dev->features |= NETIF_F_LLTX;
	dev->destructor = veth_dev_free;
}

//通过veth发送skb
2.4 static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct net_device *rcv = NULL;
	struct veth_priv *priv, *rcv_priv;
	struct veth_net_stats *stats, *rcv_stats;
	int length, cpu;

	//获取对等端
	priv = netdev_priv(dev);
	rcv = priv->peer;
	rcv_priv = netdev_priv(rcv);

	...

	//设置skb的设备为对等端
	skb->pkt_type = PACKET_HOST;
	skb->protocol = eth_type_trans(skb, rcv);
	if (dev->features & NETIF_F_NO_CSUM)
		skb->ip_summed = rcv_priv->ip_summed;

	...
	//将skb放入到对等端的接收队列中,从此完成了skb向对等端的发送
	netif_rx(skb);
	return NETDEV_TX_OK;

tx_drop:
	kfree_skb(skb);
	stats->tx_dropped++;
	return NETDEV_TX_OK;

rx_drop:
	kfree_skb(skb);
	rcv_stats->rx_dropped++;
	return NETDEV_TX_OK;
}