// Use veth // 1. create two virtual network adapters (veth1 and veth2), and connect them point to point. Then, the data of the two network adapters will be sent to each other. $ IP link add veth1 type veth peer name veth2 // 2. create a network namespace T1 $ IP netns add T1 // 3. after veth0 is added to T1, veth0 is invisible because $ IP link set veth0 netns t1/4 is added to other namespaces. configure the IP address of veth0 $ IP netns exec T1 ifconfig eth0 192.168.1.200/24 // 5. set the default route for T1 network $ IP netns exec T1 route add default GW 192.168.1.1 // 6. now, you can add veth2 to the ingress Network Bridge to enable veth1 to access the external network in T1. The process is omitted. Refer to the network configuration steps in docker/ve Th implementation method (Drivers/NET/veth. c) // register the Service 1.1 static _ init int veth_init (void) {return rtnl_link_register (& veth_link_ops );} // process the IP link command 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,}; // Add a new veth link 2.2 static in T 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; // create and register peerif (Data! = NULL & Data [veth_info_peer]! = NULL) {struct nlattr * nla_peer; // parse the command line parameter 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 );...} elsetbp = Tb; // initialize peer... // register peererr = register_netdevice (PEER); If (ERR <0) goto err_register_peer; // initialize peer of peer... // register peer err = register_netdevice (Dev); If (ERR <0) goto err_register_dev; // save peer to private, use 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;} // initialize the veth device 2.3 static void veth_setup (struct net_device * Dev) {// General initialization of Ethernet devices ether_setup (Dev); // veth operation list Dev-> netdev_ops = & veth_netdev_ops; Dev-> ethtool_ops = & veth_ethtool_ops; dev-> features | = netif_f_lltx; Dev-> destructor = veth_dev_free;} // send skb2.4 static route veth_xmit (struct sk_buff * SKB, struct net_device * Dev) through veth) {struct net_device * RCV = NULL; struct veth_priv * priv, * rcv_priv; struct veth_net_stats * stats, * rcv_stats; int length, CPU; // obtain the peer priv = netdev_priv (Dev); RCV = priv-> peer; rcv_priv = netdev_priv (RCV );... // set the SKB device to the peer 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 ;... // put the SKB in the receiving queue of the Peer end, and then the SKB sends the netif_rx (SKB); Return netdev_tx_ OK; tx_drop: kfree_skb (SKB) to the peer end ); stats-> tx_dropped ++; return netdev_tx_ OK; rx_drop: kfree_skb (SKB); rcv_stats-> rx_dropped ++; return netdev_tx_ OK ;}