Add the ability to set the VLAN protocol on the netlink interfaces -- this will be needed when the VPP interface outer is dot1ad rather than dot1q; Note: this change took for-ever to create! I was stumped on the set_protocol() call succeeding but the add_link() call returning 'Protocol mismatch'; but this was simply a missing ntohs() wrapper on the protocol, pff. Golden hint on https://github.com/thom311/libnl/blob/master/lib/route/link/vlan.c#L454

This commit is contained in:
Pim van Pelt
2021-08-11 18:43:48 +02:00
parent 3c1ccbfcc6
commit 954385fd86

View File

@ -21,6 +21,7 @@
#include <lcpng/lcpng_interface.h> #include <lcpng/lcpng_interface.h>
#include <netlink/route/link/vlan.h> #include <netlink/route/link/vlan.h>
#include <linux/if_ether.h>
#include <vnet/plugin/plugin.h> #include <vnet/plugin/plugin.h>
#include <vnet/plugin/plugin.h> #include <vnet/plugin/plugin.h>
@ -339,25 +340,37 @@ lcp_itf_pair_add (u32 host_sw_if_index, u32 phy_sw_if_index, u8 *host_name,
} }
static clib_error_t * static clib_error_t *
lcp_netlink_add_link_vlan (int parent, u32 vlan, const char *name) lcp_netlink_add_link_vlan (int parent, u32 vlan, u16 proto, const char *name)
{ {
struct rtnl_link *link; struct rtnl_link *link;
struct nl_sock *sk; struct nl_sock *sk;
int err; int err;
sk = nl_socket_alloc (); sk = nl_socket_alloc ();
if ((err = nl_connect (sk, NETLINK_ROUTE)) < 0) if ((err = nl_connect (sk, NETLINK_ROUTE)) < 0) {
LCP_ITF_PAIR_ERR ("netlink_add_link_vlan: connect error: %s", nl_geterror(err));
return clib_error_return (NULL, "Unable to connect socket: %d", err); return clib_error_return (NULL, "Unable to connect socket: %d", err);
}
link = rtnl_link_vlan_alloc (); link = rtnl_link_vlan_alloc ();
rtnl_link_set_link (link, parent); rtnl_link_set_link (link, parent);
rtnl_link_set_name (link, name); rtnl_link_set_name (link, name);
rtnl_link_vlan_set_id (link, vlan); if ((err = rtnl_link_vlan_set_id (link, vlan)) < 0) {
LCP_ITF_PAIR_ERR ("netlink_add_link_vlan: vlan set error: %s", nl_geterror(err));
return clib_error_return (NULL, "Unable to set VLAN %d on link %s: %d", vlan, name, err);
}
if ((err = rtnl_link_add (sk, link, NLM_F_CREATE)) < 0) if ((err = rtnl_link_vlan_set_protocol (link, htons(proto))) < 0) {
LCP_ITF_PAIR_ERR ("netlink_add_link_vlan: proto set error: %s", nl_geterror(err));
return clib_error_return (NULL, "Unable to set proto %d on link %s: %d", proto, name, err);
}
if ((err = rtnl_link_add (sk, link, NLM_F_CREATE)) < 0) {
LCP_ITF_PAIR_ERR ("netlink_add_link_vlan: link add error: %s", nl_geterror(err));
return clib_error_return (NULL, "Unable to add link %s: %d", name, err); return clib_error_return (NULL, "Unable to add link %s: %d", name, err);
}
rtnl_link_put (link); rtnl_link_put (link);
nl_close (sk); nl_close (sk);
@ -640,6 +653,7 @@ lcp_itf_pair_create (u32 phy_sw_if_index, u8 *host_if_name,
int orig_ns_fd, ns_fd; int orig_ns_fd, ns_fd;
clib_error_t *err; clib_error_t *err;
u16 outer_vlan, inner_vlan; u16 outer_vlan, inner_vlan;
u16 outer_proto, inner_proto;
/* /*
* Find the parent tap by finding the pair from the parent phy * Find the parent tap by finding the pair from the parent phy
@ -647,6 +661,8 @@ lcp_itf_pair_create (u32 phy_sw_if_index, u8 *host_if_name,
lip = lcp_itf_pair_get (lcp_itf_pair_find_by_phy (sw->sup_sw_if_index)); lip = lcp_itf_pair_get (lcp_itf_pair_find_by_phy (sw->sup_sw_if_index));
outer_vlan = sw->sub.eth.outer_vlan_id; outer_vlan = sw->sub.eth.outer_vlan_id;
inner_vlan = sw->sub.eth.inner_vlan_id; inner_vlan = sw->sub.eth.inner_vlan_id;
outer_proto = inner_proto = ETH_P_8021Q;
if (1 == sw->sub.eth.flags.dot1ad) outer_proto = ETH_P_8021AD;
LCP_ITF_PAIR_INFO ("pair_create: trying to create %d.%d on %U", outer_vlan, inner_vlan, LCP_ITF_PAIR_INFO ("pair_create: trying to create %d.%d on %U", outer_vlan, inner_vlan,
format_vnet_sw_if_index_name, vnet_get_main (), hw->sw_if_index); format_vnet_sw_if_index_name, vnet_get_main (), hw->sw_if_index);
@ -673,18 +689,18 @@ lcp_itf_pair_create (u32 phy_sw_if_index, u8 *host_if_name,
/* /*
* no existing host interface, create it now * no existing host interface, create it now
*/ */
err = lcp_netlink_add_link_vlan (lip->lip_vif_index, outer_vlan, err = lcp_netlink_add_link_vlan (lip->lip_vif_index, outer_vlan, outer_proto,
(const char *) host_if_name); (const char *) host_if_name);
if (err != 0) { if (err != 0) {
LCP_ITF_PAIR_ERR ("pair_create: cannot create link outer.inner:%d.%d name:'%s' error: %s", LCP_ITF_PAIR_ERR ("pair_create: cannot create link outer(proto:0x%04x,vlan:%u).inner(proto:0x%04x,vlan:%u) name:'%s'",
outer_vlan, inner_vlan, host_if_name, strerror(errno)); outer_proto, outer_vlan, inner_proto, inner_vlan, host_if_name);
} }
if (!err && -1 != ns_fd) { if (!err && -1 != ns_fd) {
err = vnet_netlink_set_link_netns (vif_index, ns_fd, NULL); err = vnet_netlink_set_link_netns (vif_index, ns_fd, NULL);
if (err != 0) { if (err != 0) {
LCP_ITF_PAIR_ERR ("pair_create: cannot set link name:'%s' in namespace:'%s', error: %s", LCP_ITF_PAIR_ERR ("pair_create: cannot set link name:'%s' in namespace:'%s'",
host_if_name, ns, strerror(errno)); host_if_name, ns);
} }
} }
if (!err) if (!err)