Commit b04f754d authored by Ondrej Zajicek (work)'s avatar Ondrej Zajicek (work)
Browse files

Nest: Multicast net parsing and MIF managing

parent 32179662
Loading
Loading
Loading
Loading
+29 −1
Original line number Diff line number Diff line
@@ -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_
 ;

+3 −0
Original line number Diff line number Diff line
@@ -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); }

+4 −4
Original line number Diff line number Diff line
@@ -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);
  }
+5 −1
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
@@ -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);
}

/*
Loading