[PATCH 2/2] ip: added arguments support for veth device type.

Nicholas Niro blowfist at xroutine.net
Thu Apr 30 22:52:48 UTC 2020


This patch adds support for the "peer name" argument to 'ip link add'.
Without this patch, the veth devices pair is created but the second
linked device gets a name like 'vethN' rather than get the name
that we set with the 'peer name <new device name>' argument.

So if you did :

ip link add veIn type veth peer name veExt

you ended up with the devices 'veIn' and something like 'veth0' rather
than the expected 'veExt'.

Here's the excerp of the veth(4) man page that shows the standard way to
create a veth devices pair:

The  veth  devices  are  virtual Ethernet devices.  They can act as
tunnels between network namespaces to create a bridge to a physical
network device in another namespace, but can also be used as
standalone network devices.

veth devices are always created in interconnected pairs.  A pair
can be created using the command:

 # ip link add <p1-name> type veth peer name <p2-name>

In the above, p1-name and p2-name are the names assigned to the
two connected end points.

Signed-off-by: Nicholas Niro <blowfist at xroutine.net>

---
 networking/libiproute/iplink.c | 65 ++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/networking/libiproute/iplink.c b/networking/libiproute/iplink.c
index 68d199044..4d0a3eaf3 100644
--- a/networking/libiproute/iplink.c
+++ b/networking/libiproute/iplink.c
@@ -11,6 +11,7 @@
 #include <netinet/if_ether.h>
 
 #include <linux/if_vlan.h>
+#include <linux/veth.h>
 #include "ip_common.h"  /* #include "libbb.h" is inside */
 #include "rt_names.h"
 #include "utils.h"
@@ -614,6 +615,68 @@ static void vrf_parse_opt(char **argv, struct nlmsghdr *n, unsigned int size)
 #define NLMSG_TAIL(nmsg) \
 	((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
 #endif
+static void veth_parse_opt(char **argv, struct nlmsghdr *n, unsigned int size)
+{
+	static const char keywords[] ALIGN1 =
+		"peer\0""name\0"
+	;
+	enum {
+		ARG_peer = 0,
+		ARG_name
+	};
+	int arg;
+	struct ifinfomsg *ifm, *ifmPeer;
+	struct rtattr *data;
+	uint32_t flagsBackup, changeBackup;
+	int devIndex = 0;
+	int peer = -1;
+	char *name = NULL;
+
+	ifm = NLMSG_DATA(n);
+	flagsBackup = ifm->ifi_flags;
+	changeBackup = ifm->ifi_change;
+	ifm->ifi_flags = 0;
+	ifm->ifi_change = 0;
+
+	data = NLMSG_TAIL(n);
+
+	addattr_l(n, size, VETH_INFO_PEER, NULL, 0);
+
+	while (*argv) {
+		arg = index_in_substrings(keywords, *argv);
+		if (arg < 0)
+			invarg_1_to_2(*argv, "type veth");
+
+		if (arg == ARG_peer) {
+			peer = 1;
+		} else if (peer) {
+			if (arg == ARG_name) {
+				size_t len;
+				NEXT_ARG();
+				name = *argv;
+
+				len = strlen(name) + 1;
+				if (len > IFNAMSIZ)
+					bb_error_msg_and_die("peer name too long '%s'",
+								     *argv);
+				n->nlmsg_len += sizeof(struct ifinfomsg);
+
+				addattr_l(n, size, IFLA_IFNAME, name, len);
+			}
+		}
+		argv++;
+	}
+
+	ifmPeer = RTA_DATA(data);
+	ifmPeer->ifi_index = devIndex;
+	ifmPeer->ifi_flags = ifm->ifi_flags;
+	ifmPeer->ifi_change = ifm->ifi_change;
+	ifm->ifi_flags = flagsBackup;
+	ifm->ifi_change = changeBackup;
+
+	data->rta_len = (void *)NLMSG_TAIL(n) - (void *)data;
+}
+
 /* Return value becomes exitcode. It's okay to not return at all */
 static int do_add_or_delete(char **argv, const unsigned rtm)
 {
@@ -698,6 +761,8 @@ static int do_add_or_delete(char **argv, const unsigned rtm)
 				vlan_parse_opt(argv, &req.n, sizeof(req));
 			else if (strcmp(type_str, "vrf") == 0)
 				vrf_parse_opt(argv, &req.n, sizeof(req));
+			else if (strcmp(type_str, "veth") == 0)
+				veth_parse_opt(argv, &req.n, sizeof(req));
 
 			data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;
 		}
-- 
2.24.1.485.gad05a3d8e5.dirty



More information about the busybox mailing list