Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial VRF add/del/master support #6

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lcpng.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <vlib/vlib.h>

#define LCP_NS_LEN 32
#define LCP_HAVE_VRF_SYNC 1

typedef struct lcp_main_s
{
Expand Down
123 changes: 115 additions & 8 deletions lcpng_if_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@
* limitations under the License.
*/

#include <net/if.h>

#include <linux/rtnetlink.h>

#include <vnet/vnet.h>
#include <vnet/plugin/plugin.h>
#include <vnet/devices/netlink.h>
#include <vnet/ip/ip.h>
#include <vnet/fib/fib_table.h>
#include <vppinfra/linux/netns.h>

#include <plugins/lcpng/lcpng_interface.h>
Expand Down Expand Up @@ -492,6 +495,90 @@ lcp_itf_ip6_add_del_interface_addr (ip6_main_t *im, uword opaque,
}
}

#ifdef LCP_HAVE_VRF_SYNC
static void
lcp_itf_ipX_table_bind (fib_protocol_t proto,
u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
{
u32 new_table_id;
char if_name_buf[IF_NAMESIZE];
char *if_name;
const lcp_itf_pair_t *lip;
lcp_nl_table_t *nlt;

if (!lcp_sync ())
return;

LCP_IF_DBG ("ip%s_table_bind: si:%U fib:%u->%u",
proto == FIB_PROTOCOL_IP4 ? "4" : "6",
format_vnet_sw_if_index_name, vnet_get_main (), sw_if_index,
old_fib_index, new_fib_index);

new_table_id = fib_table_get_table_id (new_fib_index, proto);

lip = lcp_itf_pair_get (lcp_itf_pair_find_by_phy (sw_if_index));
if (!lip)
return;

if (new_table_id)
{
nlt = lcp_nl_table_find (new_table_id, FIB_PROTOCOL_IP4);
if (!nlt || nlt->nlt_if_index == ~0)
return;

if_name = if_indextoname(nlt->nlt_if_index, if_name_buf);
if (!if_name)
return;

LCP_IF_DBG ("ip%s_table_bind: %U master:%s",
proto == FIB_PROTOCOL_IP4 ? "4" : "6",
format_lcp_itf_pair, lip, if_name);

vnet_netlink_set_link_master (lip->lip_vif_index, if_name);
}
else
{
LCP_IF_DBG ("ip%s_table_bind: %U nomaster",
proto == FIB_PROTOCOL_IP4 ? "4" : "6",
format_lcp_itf_pair, lip);

vnet_netlink_set_link_master (lip->lip_vif_index, "");
}
}

static void
lcp_itf_ip4_table_bind (struct ip4_main_t * im, uword opaque,
u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
{
lcp_itf_ipX_table_bind (FIB_PROTOCOL_IP4, sw_if_index, new_fib_index, old_fib_index);
}

static void
lcp_itf_ip6_table_bind (struct ip6_main_t * im, uword opaque,
u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
{
lcp_itf_ipX_table_bind (FIB_PROTOCOL_IP6, sw_if_index, new_fib_index, old_fib_index);
}

static clib_error_t *
lcp_itf_ip_table_add_del (struct vnet_main_t * vnm, u32 table_id, u32 flags)
{
char if_name[32];
clib_error_t *err = NULL;

snprintf (if_name, sizeof(if_name), "vpp-vrf%u", table_id);
if (flags)
err = lcp_netlink_add_link_vrf (table_id, if_name);
else
{
if (fib_table_find (FIB_PROTOCOL_IP4, table_id) == ~0 ||
fib_table_find (FIB_PROTOCOL_IP6, table_id) == ~0)
err = lcp_netlink_del_link (if_name);
}
return err;
}
#endif // LCP_HAVE_VRF_SYNC

static clib_error_t *
lcp_itf_interface_add_del (vnet_main_t *vnm, u32 sw_if_index, u32 is_create)
{
Expand Down Expand Up @@ -552,16 +639,36 @@ lcp_itf_sync_init (vlib_main_t *vm)
ip4_main_t *im4 = &ip4_main;
ip6_main_t *im6 = &ip6_main;

ip4_add_del_interface_address_callback_t cb4;
ip6_add_del_interface_address_callback_t cb6;
ip4_add_del_interface_address_callback_t add_del_cb4;
ip6_add_del_interface_address_callback_t add_del_cb6;

add_del_cb4.function = lcp_itf_ip4_add_del_interface_addr;
add_del_cb4.function_opaque = 0;
vec_add1 (im4->add_del_interface_address_callbacks, add_del_cb4);

add_del_cb6.function = lcp_itf_ip6_add_del_interface_addr;
add_del_cb6.function_opaque = 0;
vec_add1 (im6->add_del_interface_address_callbacks, add_del_cb6);

#ifdef LCP_HAVE_VRF_SYNC
vnet_main_t *vnm = &vnet_main;

ip4_table_bind_callback_t bind_cb4;
bind_cb4.function = lcp_itf_ip4_table_bind;
bind_cb4.function_opaque = FIB_PROTOCOL_IP4;
vec_add1 (im4->table_bind_callbacks, bind_cb4);

cb4.function = lcp_itf_ip4_add_del_interface_addr;
cb4.function_opaque = 0;
vec_add1 (im4->add_del_interface_address_callbacks, cb4);
ip6_table_bind_callback_t bind_cb6;
bind_cb6.function = lcp_itf_ip6_table_bind;
bind_cb6.function_opaque = FIB_PROTOCOL_IP6;
vec_add1 (im6->table_bind_callbacks, bind_cb6);

cb6.function = lcp_itf_ip6_add_del_interface_addr;
cb6.function_opaque = 0;
vec_add1 (im6->add_del_interface_address_callbacks, cb6);
static _vnet_ip_table_function_list_elt_t ip_table_add_del_cb;
ip_table_add_del_cb.fp = lcp_itf_ip_table_add_del;
ip_table_add_del_cb.next_ip_table_function =
vnm->ip_table_add_del_functions[VNET_ITF_FUNC_PRIORITY_LOW];
vnm->ip_table_add_del_functions[VNET_ITF_FUNC_PRIORITY_LOW] = &ip_table_add_del_cb;
#endif // LCP_HAVE_VRF_SYNC

return NULL;
}
Expand Down
67 changes: 66 additions & 1 deletion lcpng_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include <lcpng/lcpng_interface.h>
#include <netlink/route/link/vlan.h>
#include <netlink/route/link/vrf.h>
#include <linux/if_ether.h>

#include <vnet/plugin/plugin.h>
Expand All @@ -46,6 +47,10 @@ vlib_log_class_t lcp_itf_pair_logger;
*/
lcp_itf_pair_t *lcp_itf_pair_pool = NULL;

lcp_nl_table_t *lcp_nl_table_pool = NULL;

uword *lcp_nl_table_db[FIB_PROTOCOL_MAX] = { NULL };

u32
lcp_itf_num_pairs (void)
{
Expand Down Expand Up @@ -368,7 +373,7 @@ lcp_netlink_add_link_vlan (int parent, u32 vlan, u16 proto, const char *name)
return NULL;
}

static clib_error_t *
clib_error_t *
lcp_netlink_del_link (const char *name)
{
struct rtnl_link *link;
Expand Down Expand Up @@ -1200,6 +1205,66 @@ lcp_itf_pair_init (vlib_main_t *vm)
return NULL;
}

lcp_nl_table_t *
lcp_nl_table_find (uint32_t id, fib_protocol_t fproto)
{
uword *p;

p = hash_get (lcp_nl_table_db[fproto], id);

if (p)
return pool_elt_at_index (lcp_nl_table_pool, p[0]);

return (NULL);
}

#ifdef LCP_HAVE_VRF_SYNC
lcp_nl_table_t *
lcp_nl_table_find_by_if_index (u32 if_index)
{
lcp_nl_table_t *nlt;

pool_foreach (nlt, lcp_nl_table_pool)
{
if (nlt->nlt_proto == FIB_PROTOCOL_IP4 && nlt->nlt_if_index == if_index)
return nlt;
}
return NULL;
}

clib_error_t *
lcp_netlink_add_link_vrf (u32 table_id, const char *name)
{
struct rtnl_link *link;
struct nl_sock *sk;
int err;

sk = nl_socket_alloc ();
if ((err = nl_connect (sk, NETLINK_ROUTE)) < 0) {
LCP_IF_ERROR ("netlink_add_link_vrf: Netlink connect error: %s",
nl_geterror (err));
return clib_error_return (NULL, "Unable to connect socket: %d", err);
}

link = rtnl_link_vrf_alloc ();

rtnl_link_set_link (link, 0);
rtnl_link_set_name (link, name);
rtnl_link_vrf_set_tableid (link, table_id);

if ((err = rtnl_link_add (sk, link, NLM_F_CREATE)) < 0) {
LCP_IF_ERROR ("netlink_add_link_vrf: Netlink link add error: %s",
nl_geterror (err));
return clib_error_return (NULL, "Unable to add link %s: %d", name, err);
}

rtnl_link_put (link);
nl_close (sk);

return NULL;
}
#endif // LCP_HAVE_VRF_SYNC

VLIB_INIT_FUNCTION (lcp_itf_pair_init) = {
.runs_after = VLIB_INITS ("vnet_interface_init", "tcp_init", "udp_init"),
};
Expand Down
22 changes: 22 additions & 0 deletions lcpng_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,19 @@ typedef struct lcp_itf_pair_t_
} lcp_itf_pair_t;
extern lcp_itf_pair_t *lcp_itf_pair_pool;

typedef struct lcp_nl_table_t_
{
uint32_t nlt_id;
fib_protocol_t nlt_proto;
u32 nlt_fib_index;
u32 nlt_mfib_index;
u32 nlt_refs;
u32 nlt_if_index;
} lcp_nl_table_t;
extern lcp_nl_table_t *lcp_nl_table_pool;

extern uword *lcp_nl_table_db[FIB_PROTOCOL_MAX];

extern vlib_node_registration_t lcp_ethernet_node;

u8 *format_lcp_itf_pair (u8 *s, va_list *args);
Expand Down Expand Up @@ -166,6 +179,8 @@ int lcp_auto_subint (void);
void lcp_set_sync (u8 is_auto);
int lcp_sync (void);

clib_error_t *lcp_netlink_del_link (const char *name);

typedef void (*lcp_itf_pair_add_cb_t) (lcp_itf_pair_t *);
typedef void (*lcp_itf_pair_del_cb_t) (lcp_itf_pair_t *);

Expand Down Expand Up @@ -194,6 +209,13 @@ void lcp_itf_pair_sync_state (lcp_itf_pair_t *lip);
void lcp_itf_pair_sync_state_hw (vnet_hw_interface_t *hi);
void lcp_itf_pair_sync_state_all ();

lcp_nl_table_t *lcp_nl_table_find (uint32_t id, fib_protocol_t fproto);

#ifdef LCP_HAVE_VRF_SYNC
lcp_nl_table_t *lcp_nl_table_find_by_if_index (u32 if_index);
clib_error_t *lcp_netlink_add_link_vrf (u32 table_id, const char *name);
#endif // LCP_HAVE_VRF_SYNC

/*
* fd.io coding-style-patch-verification: ON
*
Expand Down
5 changes: 5 additions & 0 deletions lcpng_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ format_nl_object (u8 *s, va_list *args)
{
struct rtnl_link *link = (struct rtnl_link *) obj;
struct nl_addr *a;
int master;
char buf[128];
// mac_addr = rtnl_link_get_addr (l);
s =
Expand All @@ -177,6 +178,10 @@ format_nl_object (u8 *s, va_list *args)
if (buf[0])
s = format (s, " (%s)", buf);

master = rtnl_link_get_master (link);
if (master)
s = format (s, " master %d", master);

if (rtnl_link_is_vlan (link))
{
s =
Expand Down
12 changes: 1 addition & 11 deletions lcpng_netlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <netlink/route/neighbour.h>
#include <netlink/route/addr.h>
#include <netlink/route/link/vlan.h>
#include <netlink/route/link/vrf.h>

#include <vnet/fib/fib_table.h>
#include <vnet/mfib/mfib_table.h>
Expand Down Expand Up @@ -66,15 +67,6 @@ typedef struct lcp_nl_netlink_namespace
u8 *netns_name; // namespace name (can be empty, for 'self')
} lcp_nl_netlink_namespace_t;

typedef struct lcp_nl_table_t_
{
uint32_t nlt_id;
fib_protocol_t nlt_proto;
u32 nlt_fib_index;
u32 nlt_mfib_index;
u32 nlt_refs;
} lcp_nl_table_t;

typedef struct lcp_nl_main
{
vlib_log_class_t nl_logger;
Expand All @@ -86,8 +78,6 @@ typedef struct lcp_nl_main
fib_source_t fib_src; // For static routes set manually
fib_source_t
fib_src_dynamic; // For routes set by routing software (Bird, FRR, etc)
uword *table_db[FIB_PROTOCOL_MAX];
lcp_nl_table_t *table_pool;

u32 rx_buf_size;
u32 tx_buf_size;
Expand Down
Loading