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:
parent
321796628f
commit
b04f754d86
@ -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_
|
||||
;
|
||||
|
||||
|
@ -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); }
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
57
nest/iface.c
57
nest/iface.c
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
22
nest/iface.h
22
nest/iface.h
@ -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 */
|
||||
|
||||
|
17
nest/route.h
17
nest/route.h
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user