0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2025-02-02 14:20:01 +00:00

Nest: Multicast net parsing and MIF managing

This commit is contained in:
Ondrej Zajicek (work) 2018-02-22 16:51:43 +01:00
parent 321796628f
commit b04f754d86
8 changed files with 164 additions and 9 deletions

View File

@ -83,7 +83,7 @@ CF_DECLS
%type <time> expr_us time
%type <a> ipa
%type <net> net_ip4_ net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa
%type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_ net_mpls_
%type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_ net_mreq4_ net_mreq6_ net_mreq_ net_mgrp4_ net_mgrp6_ net_mgrp_ net_mpls_
%type <mls> label_stack_start label_stack
%type <t> text opttext
@ -234,6 +234,30 @@ net_roa6_: net_ip6_ MAX NUM AS NUM
cf_error("Invalid max prefix length %u", $3);
};
net_mreq4_: MREQ4 '(' '*' ',' IP4 ')'
{
$$ = cfg_alloc(sizeof(net_addr_mreq4));
net_fill_mreq4($$, $5, 0); // XXXX
}
net_mreq6_: MREQ6 '(' '*' ',' IP6 ')'
{
$$ = cfg_alloc(sizeof(net_addr_mreq6));
net_fill_mreq6($$, $5, 0); // XXXX
}
net_mgrp4_: MGRP4 '(' '*' ',' IP4 ')'
{
$$ = cfg_alloc(sizeof(net_addr_mgrp4));
net_fill_mgrp4($$, $5);
}
net_mgrp6_: MGRP6 '(' '*' ',' IP6 ')'
{
$$ = cfg_alloc(sizeof(net_addr_mgrp6));
net_fill_mgrp6($$, $5);
}
net_mpls_: MPLS NUM
{
$$ = cfg_alloc(sizeof(net_addr_roa6));
@ -243,12 +267,16 @@ net_mpls_: MPLS NUM
net_ip_: net_ip4_ | net_ip6_ ;
net_vpn_: net_vpn4_ | net_vpn6_ ;
net_roa_: net_roa4_ | net_roa6_ ;
net_mreq_: net_mreq4_ | net_mreq6_ ;
net_mgrp_: net_mgrp4_ | net_mgrp6_ ;
net_:
net_ip_ { $$ = cfg_alloc($1.length); net_copy($$, &($1)); }
| net_vpn_
| net_roa_
| net_flow_
| net_mreq_
| net_mgrp_
| net_mpls_
;

View File

@ -40,6 +40,9 @@ struct align_probe { char x; long int y; };
#define CALL(fn, args...) ({ if (fn) fn(args); })
#define ADVANCE(w, r, l) ({ r -= l; w += l; })
#define WALK_ARRAY(v,l,n) \
for (typeof(*(v)) *_n = (v), n; _n < ((v) + (l)) && (n = *_n, 1); _n++)
static inline int uint_cmp(uint i1, uint i2)
{ return (int)(i1 > i2) - (int)(i1 < i2); }

View File

@ -64,8 +64,8 @@ const u16 net_max_text_length[] = {
[NET_FLOW6] = 0, /* "flow6 { ... }" */
[NET_MREQ4] = 15, /* "255.255.255.255" */
[NET_MREQ6] = 39, /* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" */
[NET_MGRP4] = 15, /* "255.255.255.255" */
[NET_MGRP6] = 39, /* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" */
[NET_MGRP4] = 20, /* "(*, 255.255.255.255)" */
[NET_MGRP6] = 44, /* "(*, ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff)" */
[NET_MPLS] = 7, /* "1048575" */
};
@ -123,9 +123,9 @@ net_format(const net_addr *N, char *buf, int buflen)
case NET_MREQ6:
return bsnprintf(buf, buflen, "%I6", n->mreq6.grp);
case NET_MGRP4:
return bsnprintf(buf, buflen, "%I4", n->mgrp4.grp);
return bsnprintf(buf, buflen, "(*, %I4)", n->mgrp4.grp);
case NET_MGRP6:
return bsnprintf(buf, buflen, "%I6", n->mgrp6.grp);
return bsnprintf(buf, buflen, "(*, %I6)", n->mgrp6.grp);
case NET_MPLS:
return bsnprintf(buf, buflen, "%u", n->mpls.label);
}

View File

@ -49,10 +49,14 @@
#define NB_MREQ (NB_MREQ4 | NB_MREQ6)
#define NB_MGRP (NB_MGRP4 | NB_MGRP6)
/* FIXME: Better validation of (NET, RTD) combinations */
#define NB_HOST (NB_IP | NB_VPN | NB_ROA)
#define NB_DEST (NB_IP | NB_VPN | NB_MPLS)
// #define NB_DEST (NB_IP | NB_VPN | NB_MPLS)
#define NB_DEST (NB_IP | NB_VPN | NB_MGRP | NB_MPLS)
#define NB_ANY 0xffffffff
#define MIFS_MAX 32
typedef struct net_addr {
u8 type;

View File

@ -37,8 +37,10 @@
static pool *if_pool;
list iface_list;
struct mif_group *global_mif_group;
static void if_recalc_preferred(struct iface *i);
static struct mif_group *mif_get_group(void);
/**
* ifa_dump - dump interface address
@ -714,6 +716,61 @@ if_init(void)
if_pool = rp_new(&root_pool, "Interfaces");
init_list(&iface_list);
neigh_init(if_pool);
global_mif_group = mif_get_group();
}
/*
* Multicast Ifaces
*/
static struct mif_group *
mif_get_group(void)
{
struct mif_group *grp = mb_allocz(if_pool, sizeof(struct mif_group));
init_list(&grp->sockets);
return grp;
}
static inline int u32_cto(uint x) { return ffs(~x) - 1; }
struct mif *
mif_get(struct mif_group *grp, struct iface *iface)
{
WALK_ARRAY(grp->mifs, MIFS_MAX, mif)
if (mif && (mif->iface == iface))
return mif->uc++, mif;
int i = u32_cto(grp->indexes);
if (i < 0)
return NULL;
struct mif *mif = mb_allocz(if_pool, sizeof(struct mif));
mif->iface = iface;
mif->index = i;
mif->uc = 1;
init_list(&mif->sockets);
grp->mifs[mif->index] = mif;
MIFS_SET(mif, grp->indexes);
return mif;
}
void
mif_free(struct mif_group *grp, struct mif *mif)
{
if (--mif->uc)
return;
node *n;
WALK_LIST_FIRST(n, mif->sockets)
rem_node(n);
grp->mifs[mif->index] = NULL;
MIFS_CLR(mif, grp->indexes);
mb_free(mif);
}
/*

View File

@ -13,6 +13,7 @@
#include "lib/ip.h"
extern list iface_list;
extern struct mif_group *global_mif_group;
struct proto;
struct pool;
@ -44,6 +45,20 @@ struct iface {
list neighbors; /* All neighbors on this interface */
};
struct mif {
struct iface *iface;
uint index; /* MIF (VIF) index for multicast routes */
uint uc; /* Use count */
list sockets; /* Listening per-iface IGMP sockets */
};
struct mif_group {
uint indexes;
uint uc; /* Use count, not implemented */
list sockets; /* Listening global IGMP sockets */
struct mif *mifs[MIFS_MAX];
};
#define IF_UP 1 /* Currently just IF_ADMIN_UP */
#define IF_MULTIACCESS 2
#define IF_BROADCAST 4
@ -115,6 +130,13 @@ struct iface *if_find_by_name(char *);
struct iface *if_get_by_name(char *);
void if_recalc_all_preferred_addresses(void);
struct mif *mif_get(struct mif_group *grp, struct iface *iface);
void mif_free(struct mif_group *grp, struct mif *mif);
#define MIFS_SET(mif,m) ((m) |= (1 << (mif)->index))
#define MIFS_CLR(mif,m) ((m) &= ~(1 << (mif)->index))
#define MIFS_ISSET(mif,m) ((m) & (1 << (mif)->index))
/* The Neighbor Cache */

View File

@ -152,6 +152,7 @@ typedef struct rtable {
int pipe_busy; /* Pipe loop detection */
int use_count; /* Number of protocols using this table */
struct hostcache *hostcache;
// struct mif_group *mif_group;
struct rtable_config *config; /* Configuration of this table */
struct config *deleted; /* Table doesn't exist in current configuration,
* delete as soon as use_count becomes 0 and remove
@ -249,9 +250,6 @@ typedef struct rte {
u8 best; /* Best route in network, propagated to core */
u32 metric; /* Kernel metric */
} krt;
struct {
u32 iifs, oifs; /* Bitmaps for iifs and oifs. Use RTE_MGRP_* macros to manipulate. */
} mkrt;
} u;
} rte;
@ -637,6 +635,19 @@ rta_set_recursive_next_hop(rtable *dep, rta *a, rtable *tab, ip_addr gw, ip_addr
rta_apply_hostentry(a, rt_get_hostentry(tab, gw, ll, dep), mls);
}
/* For RTD_MULTICAST, we encode iifs and oifs to nh.gw */
static inline u32 rta_iifs(rta *a)
{ return _I0(a->nh.gw); }
static inline void rta_set_iifs(rta *a, u32 val)
{ _I0(a->nh.gw) = val; }
static inline u32 rta_oifs(rta *a)
{ return _I1(a->nh.gw); }
static inline void rta_set_oifs(rta *a, u32 val)
{ _I1(a->nh.gw) = val; }
/*
* rta_set_recursive_next_hop() acquires hostentry from hostcache and fills
* rta->hostentry field. New hostentry has zero use count. Cached rta locks its

View File

@ -28,6 +28,30 @@ rt_show_table(struct cli *c, struct rt_show_data *d)
d->last_table = d->tab;
}
static void
rt_show_mifs(char *key, struct mif_group *grp, u32 mifs)
{
uint blen = 512;
char *buf = alloca(blen + 8);
char *pos = buf;
pos[0] = 0;
WALK_ARRAY(grp->mifs, MIFS_MAX, mif)
if (mif && MIFS_ISSET(mif, mifs))
{
int i = bsnprintf(pos, blen, " %s", mif->iface->name);
if (i < 0)
{
bsprintf(pos, " ...");
break;
}
ADVANCE(pos, blen, i);
}
cli_msg(-1007, "%s%s", key, buf);
}
static void
rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tmpa)
{
@ -92,6 +116,12 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm
nh->iface->name, mpls, onlink, weight);
}
if (a->dest == RTD_MULTICAST)
{
rt_show_mifs("\tfrom", global_mif_group, rta_iifs(a));
rt_show_mifs("\tto", global_mif_group, rta_oifs(a));
}
if (d->verbose)
rta_show(c, a, tmpa);
}