mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 09:41:54 +00:00
Filter: Ethernet and EVPN support
This commit is contained in:
parent
dc17f1982f
commit
c5c9bd811b
@ -126,6 +126,7 @@ f_valid_set_type(int type)
|
|||||||
case T_EC:
|
case T_EC:
|
||||||
case T_LC:
|
case T_LC:
|
||||||
case T_RD:
|
case T_RD:
|
||||||
|
case T_MAC:
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -357,7 +358,7 @@ CF_DECLS
|
|||||||
CF_KEYWORDS_EXCLUSIVE(IN)
|
CF_KEYWORDS_EXCLUSIVE(IN)
|
||||||
CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
|
CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
|
||||||
ACCEPT, REJECT, ERROR,
|
ACCEPT, REJECT, ERROR,
|
||||||
INT, BOOL, IP, PREFIX, RD, PAIR, QUAD, EC, LC,
|
INT, BOOL, IP, PREFIX, RD, MAC, PAIR, QUAD, EC, LC,
|
||||||
SET, STRING, BYTESTRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST,
|
SET, STRING, BYTESTRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST,
|
||||||
IF, THEN, ELSE, CASE,
|
IF, THEN, ELSE, CASE,
|
||||||
FOR, DO,
|
FOR, DO,
|
||||||
@ -455,6 +456,7 @@ type:
|
|||||||
| BOOL { $$ = T_BOOL; }
|
| BOOL { $$ = T_BOOL; }
|
||||||
| IP { $$ = T_IP; }
|
| IP { $$ = T_IP; }
|
||||||
| RD { $$ = T_RD; }
|
| RD { $$ = T_RD; }
|
||||||
|
| MAC { $$ = T_MAC; }
|
||||||
| PREFIX { $$ = T_NET; }
|
| PREFIX { $$ = T_NET; }
|
||||||
| PAIR { $$ = T_PAIR; }
|
| PAIR { $$ = T_PAIR; }
|
||||||
| QUAD { $$ = T_QUAD; }
|
| QUAD { $$ = T_QUAD; }
|
||||||
@ -475,8 +477,9 @@ type:
|
|||||||
case T_QUAD:
|
case T_QUAD:
|
||||||
case T_EC:
|
case T_EC:
|
||||||
case T_LC:
|
case T_LC:
|
||||||
case T_RD:
|
|
||||||
case T_IP:
|
case T_IP:
|
||||||
|
case T_RD:
|
||||||
|
case T_MAC:
|
||||||
$$ = T_SET;
|
$$ = T_SET;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -640,6 +643,7 @@ set_atom:
|
|||||||
NUM { $$.type = T_INT; $$.val.i = $1; }
|
NUM { $$.type = T_INT; $$.val.i = $1; }
|
||||||
| fipa { $$ = $1; }
|
| fipa { $$ = $1; }
|
||||||
| VPN_RD { $$.type = T_RD; $$.val.ec = $1; }
|
| VPN_RD { $$.type = T_RD; $$.val.ec = $1; }
|
||||||
|
| MAC_ { $$.type = T_MAC; $$.val.mac = $1; }
|
||||||
| ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); }
|
| ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); }
|
||||||
| '(' term ')' {
|
| '(' term ')' {
|
||||||
$$ = cf_eval($2, T_VOID);
|
$$ = cf_eval($2, T_VOID);
|
||||||
@ -797,6 +801,7 @@ constant:
|
|||||||
| BYTETEXT { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_BYTESTRING, .val.bs = $1, }); }
|
| BYTETEXT { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_BYTESTRING, .val.bs = $1, }); }
|
||||||
| fipa { $$ = f_new_inst(FI_CONSTANT, $1); }
|
| fipa { $$ = f_new_inst(FI_CONSTANT, $1); }
|
||||||
| VPN_RD { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_RD, .val.ec = $1, }); }
|
| VPN_RD { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_RD, .val.ec = $1, }); }
|
||||||
|
| MAC_ { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_MAC, .val.mac = $1, }); }
|
||||||
| net_ { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_NET, .val.net = $1, }); }
|
| net_ { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_NET, .val.net = $1, }); }
|
||||||
| '[' ']' { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_SET, .val.t = NULL, }); }
|
| '[' ']' { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_SET, .val.t = NULL, }); }
|
||||||
| '[' set_items ']' {
|
| '[' set_items ']' {
|
||||||
|
@ -43,6 +43,8 @@ static const char * const f_type_str[] = {
|
|||||||
[T_ENUM_NETTYPE] = "enum nettype",
|
[T_ENUM_NETTYPE] = "enum nettype",
|
||||||
[T_ENUM_RA_PREFERENCE] = "enum ra_preference",
|
[T_ENUM_RA_PREFERENCE] = "enum ra_preference",
|
||||||
[T_ENUM_AF] = "enum af",
|
[T_ENUM_AF] = "enum af",
|
||||||
|
[T_ENUM_MPLS_POLICY] = "enum mpls_policy",
|
||||||
|
[T_ENUM_NET_EVPN] = "enum net_evpn",
|
||||||
|
|
||||||
[T_IP] = "ip",
|
[T_IP] = "ip",
|
||||||
[T_NET] = "prefix",
|
[T_NET] = "prefix",
|
||||||
@ -56,6 +58,7 @@ static const char * const f_type_str[] = {
|
|||||||
[T_LC] = "lc",
|
[T_LC] = "lc",
|
||||||
[T_LCLIST] = "lclist",
|
[T_LCLIST] = "lclist",
|
||||||
[T_RD] = "rd",
|
[T_RD] = "rd",
|
||||||
|
[T_MAC] = "mac",
|
||||||
|
|
||||||
[T_ROUTE] = "route",
|
[T_ROUTE] = "route",
|
||||||
[T_ROUTES_BLOCK] = "block of routes",
|
[T_ROUTES_BLOCK] = "block of routes",
|
||||||
@ -206,6 +209,8 @@ val_compare(const struct f_val *v1, const struct f_val *v2)
|
|||||||
return lcomm_cmp(v1->val.lc, v2->val.lc);
|
return lcomm_cmp(v1->val.lc, v2->val.lc);
|
||||||
case T_IP:
|
case T_IP:
|
||||||
return ipa_compare(v1->val.ip, v2->val.ip);
|
return ipa_compare(v1->val.ip, v2->val.ip);
|
||||||
|
case T_MAC:
|
||||||
|
return mac_compare(v1->val.mac, v2->val.mac);
|
||||||
case T_NET:
|
case T_NET:
|
||||||
return net_compare(v1->val.net, v2->val.net);
|
return net_compare(v1->val.net, v2->val.net);
|
||||||
case T_STRING:
|
case T_STRING:
|
||||||
@ -633,6 +638,7 @@ val_format(const struct f_val *v, buffer *buf)
|
|||||||
case T_EC: ec_format(buf2, v->val.ec); buffer_print(buf, "%s", buf2); return;
|
case T_EC: ec_format(buf2, v->val.ec); buffer_print(buf, "%s", buf2); return;
|
||||||
case T_LC: lc_format(buf2, v->val.lc); buffer_print(buf, "%s", buf2); return;
|
case T_LC: lc_format(buf2, v->val.lc); buffer_print(buf, "%s", buf2); return;
|
||||||
case T_RD: rd_format(v->val.ec, buf2, 1024); buffer_print(buf, "%s", buf2); return;
|
case T_RD: rd_format(v->val.ec, buf2, 1024); buffer_print(buf, "%s", buf2); return;
|
||||||
|
case T_MAC: buffer_print(buf, "%6b", v->val.mac.addr); return;
|
||||||
case T_PREFIX_SET: trie_format(v->val.ti, buf); return;
|
case T_PREFIX_SET: trie_format(v->val.ti, buf); return;
|
||||||
case T_SET: tree_format(v->val.t, buf); return;
|
case T_SET: tree_format(v->val.t, buf); return;
|
||||||
case T_ENUM: buffer_print(buf, "(enum %x)%u", v->type, v->val.i); return;
|
case T_ENUM: buffer_print(buf, "(enum %x)%u", v->type, v->val.i); return;
|
||||||
|
@ -43,6 +43,7 @@ enum f_type {
|
|||||||
T_ENUM_RA_PREFERENCE = 0x37,
|
T_ENUM_RA_PREFERENCE = 0x37,
|
||||||
T_ENUM_AF = 0x38,
|
T_ENUM_AF = 0x38,
|
||||||
T_ENUM_MPLS_POLICY = 0x39,
|
T_ENUM_MPLS_POLICY = 0x39,
|
||||||
|
T_ENUM_NET_EVPN = 0x3a,
|
||||||
|
|
||||||
/* new enums go here */
|
/* new enums go here */
|
||||||
T_ENUM_EMPTY = 0x3f, /* Special hack for atomic_aggr */
|
T_ENUM_EMPTY = 0x3f, /* Special hack for atomic_aggr */
|
||||||
@ -63,6 +64,7 @@ enum f_type {
|
|||||||
T_RD = 0x2a, /* Route distinguisher for VPN addresses */
|
T_RD = 0x2a, /* Route distinguisher for VPN addresses */
|
||||||
T_PATH_MASK_ITEM = 0x2b, /* Path mask item for path mask constructors */
|
T_PATH_MASK_ITEM = 0x2b, /* Path mask item for path mask constructors */
|
||||||
T_BYTESTRING = 0x2c,
|
T_BYTESTRING = 0x2c,
|
||||||
|
T_MAC = 0x2d,
|
||||||
|
|
||||||
T_ROUTE = 0x78,
|
T_ROUTE = 0x78,
|
||||||
T_ROUTES_BLOCK = 0x79,
|
T_ROUTES_BLOCK = 0x79,
|
||||||
@ -86,6 +88,7 @@ struct f_val {
|
|||||||
u64 ec;
|
u64 ec;
|
||||||
lcomm lc;
|
lcomm lc;
|
||||||
ip_addr ip;
|
ip_addr ip;
|
||||||
|
mac_addr mac;
|
||||||
const net_addr *net;
|
const net_addr *net;
|
||||||
const char *s;
|
const char *s;
|
||||||
const struct adata *bs;
|
const struct adata *bs;
|
||||||
|
113
filter/f-inst.c
113
filter/f-inst.c
@ -1046,16 +1046,117 @@
|
|||||||
]]);
|
]]);
|
||||||
|
|
||||||
/* Convert prefix to IP */
|
/* Convert prefix to IP */
|
||||||
METHOD_R(T_NET, ip, T_IP, ip, net_prefix(v1.val.net));
|
METHOD(T_NET, ip, 0, [[
|
||||||
|
const net_addr_union *net = (void *) v1.val.net;
|
||||||
|
|
||||||
|
if ((net->n.type == NET_EVPN) && (net->evpn.subtype == NET_EVPN_MAC))
|
||||||
|
RESULT(T_IP, ip, (net->n.length == sizeof(net_addr_evpn_mac_ip)) ? net->evpn.mac_ip.ip : IPA_NONE);
|
||||||
|
else
|
||||||
|
RESULT(T_IP, ip, net_prefix(v1.val.net));
|
||||||
|
]]);
|
||||||
|
|
||||||
|
/* Get route distinguisher */
|
||||||
|
METHOD(T_NET, rd, 0, [[
|
||||||
|
if (!net_type_match(v1.val.net, NB_VPN | NB_EVPN))
|
||||||
|
runtime( "VPN or EVPN address expected" );
|
||||||
|
|
||||||
INST(FI_ROUTE_DISTINGUISHER, 1, 1) {
|
|
||||||
ARG(1, T_NET);
|
|
||||||
METHOD_CONSTRUCTOR("rd");
|
|
||||||
if (!net_is_vpn(v1.val.net))
|
|
||||||
runtime( "VPN address expected" );
|
|
||||||
RESULT(T_RD, ec, net_rd(v1.val.net));
|
RESULT(T_RD, ec, net_rd(v1.val.net));
|
||||||
|
]]);
|
||||||
|
|
||||||
|
/* Get MAC address */
|
||||||
|
METHOD(T_NET, mac, 0, [[
|
||||||
|
const net_addr_union *net = (void *) v1.val.net;
|
||||||
|
|
||||||
|
if (net->n.type == NET_ETH)
|
||||||
|
RESULT(T_MAC, mac, net->eth.mac);
|
||||||
|
else if ((net->n.type == NET_EVPN) && (net->evpn.subtype == NET_EVPN_MAC))
|
||||||
|
RESULT(T_MAC, mac, net->evpn.mac.mac);
|
||||||
|
else
|
||||||
|
runtime( "Ethernet or EVPN MAC expected" );
|
||||||
|
]]);
|
||||||
|
|
||||||
|
/* Get VLAN ID */
|
||||||
|
METHOD(T_NET, vlan_id, 0, [[
|
||||||
|
if (v1.val.net->type != NET_ETH)
|
||||||
|
runtime( "Ethernet address expected" );
|
||||||
|
|
||||||
|
const net_addr_eth *eth = (void *) v1.val.net;
|
||||||
|
RESULT(T_INT, i, eth->vid);
|
||||||
|
]]);
|
||||||
|
|
||||||
|
/* Get EVPN type */
|
||||||
|
METHOD(T_NET, evpn_type, 0, [[
|
||||||
|
if (v1.val.net->type != NET_EVPN)
|
||||||
|
runtime( "EVPN address expected" );
|
||||||
|
|
||||||
|
const net_addr_evpn *evpn = (void *) v1.val.net;
|
||||||
|
RESULT(T_ENUM_NET_EVPN, i, evpn->subtype);
|
||||||
|
]]);
|
||||||
|
|
||||||
|
/* Get EVPN tag */
|
||||||
|
METHOD(T_NET, evpn_tag, 0, [[
|
||||||
|
if (v1.val.net->type != NET_EVPN)
|
||||||
|
runtime( "EVPN address expected" );
|
||||||
|
|
||||||
|
const net_addr_evpn *evpn = (void *) v1.val.net;
|
||||||
|
if (evpn->subtype > NET_EVPN_IMET)
|
||||||
|
runtime( "EVPN EAD/MAC/IMET address expected" );
|
||||||
|
|
||||||
|
RESULT(T_INT, i, evpn->tag);
|
||||||
|
]]);
|
||||||
|
|
||||||
|
/* Get EVPN ESI */
|
||||||
|
METHOD(T_NET, evpn_esi, 0, [[
|
||||||
|
if (v1.val.net->type != NET_EVPN)
|
||||||
|
runtime( "EVPN address expected" );
|
||||||
|
|
||||||
|
const net_addr_evpn *evpn = (void *) v1.val.net;
|
||||||
|
const evpn_esi *esi;
|
||||||
|
|
||||||
|
switch (evpn->subtype)
|
||||||
|
{
|
||||||
|
case NET_EVPN_EAD:
|
||||||
|
esi = &evpn->ead.esi;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NET_EVPN_ES:
|
||||||
|
esi = &evpn->es.esi;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
runtime( "EVPN EAD/ES address expected" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct adata *bs;
|
||||||
|
bs = falloc(sizeof(struct adata) + sizeof(evpn_esi));
|
||||||
|
bs->length = sizeof(evpn_esi);
|
||||||
|
memcpy(bs->data, esi, sizeof(evpn_esi));
|
||||||
|
|
||||||
|
RESULT(T_BYTESTRING, bs, bs);
|
||||||
|
]]);
|
||||||
|
|
||||||
|
/* Get EVPN outer IP */
|
||||||
|
METHOD(T_NET, router_ip, 0, [[
|
||||||
|
if (v1.val.net->type != NET_EVPN)
|
||||||
|
runtime( "EVPN address expected" );
|
||||||
|
|
||||||
|
const net_addr_evpn *evpn = (void *) v1.val.net;
|
||||||
|
|
||||||
|
switch (evpn->subtype)
|
||||||
|
{
|
||||||
|
case NET_EVPN_IMET:
|
||||||
|
RESULT(T_IP, ip, evpn->imet.rtr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NET_EVPN_ES:
|
||||||
|
RESULT(T_IP, ip, evpn->es.rtr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
runtime( "EVPN IMET/ES address expected" );
|
||||||
|
}
|
||||||
|
]]);
|
||||||
|
|
||||||
/* Get first ASN from AS PATH */
|
/* Get first ASN from AS PATH */
|
||||||
METHOD_R(T_PATH, first, T_INT, i, ({ u32 as = 0; as_path_get_first(v1.val.ad, &as); as; }));
|
METHOD_R(T_PATH, first, T_INT, i, ({ u32 as = 0; as_path_get_first(v1.val.ad, &as); as; }));
|
||||||
|
|
||||||
|
101
filter/test.conf
101
filter/test.conf
@ -1830,6 +1830,107 @@ bt_test_suite(t_net_sadr, "Testing IPv6 SADR nets");
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Testing Ethernet nets
|
||||||
|
* ---------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
function t_net_eth()
|
||||||
|
{
|
||||||
|
prefix p;
|
||||||
|
|
||||||
|
p = eth 12:3f:c9:48:9c:9b;
|
||||||
|
bt_assert(format(p) = "12:3f:c9:48:9c:9b");
|
||||||
|
bt_assert(p.type = NET_ETH);
|
||||||
|
bt_assert(p.mac = 12:3f:c9:48:9c:9b);
|
||||||
|
bt_assert(p.vlan_id = 0);
|
||||||
|
|
||||||
|
p = eth 16:36:f8:80:5b:48 vlan 100;
|
||||||
|
bt_assert(format(p) = "16:36:f8:80:5b:48 vlan 100");
|
||||||
|
bt_assert(p.type = NET_ETH);
|
||||||
|
bt_assert(p.mac = 16:36:f8:80:5b:48);
|
||||||
|
bt_assert(p.vlan_id = 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
bt_test_suite(t_net_eth, "Testing Ethernet nets");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Testing EVPN nets
|
||||||
|
* -----------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
function t_net_evpn()
|
||||||
|
{
|
||||||
|
prefix p;
|
||||||
|
|
||||||
|
p = evpn ead 10:1010 210 00:10:20:30:40:50:60:70:80:90;
|
||||||
|
bt_assert(format(p) = "evpn ead 10:1010 210 00:10:20:30:40:50:60:70:80:90");
|
||||||
|
bt_assert(p.type = NET_EVPN);
|
||||||
|
bt_assert(p.evpn_type = NET_EVPN_EAD);
|
||||||
|
bt_assert(p.rd = 10:1010);
|
||||||
|
bt_assert(p.evpn_tag = 210);
|
||||||
|
bt_assert(p.evpn_esi = 00:10:20:30:40:50:60:70:80:90);
|
||||||
|
|
||||||
|
p = evpn mac 10:1020 220 12:a6:54:da:bc:bf *;
|
||||||
|
bt_assert(format(p) = "evpn mac 10:1020 220 12:a6:54:da:bc:bf *");
|
||||||
|
bt_assert(p.type = NET_EVPN);
|
||||||
|
bt_assert(p.evpn_type = NET_EVPN_MAC);
|
||||||
|
bt_assert(p.rd = 10:1020);
|
||||||
|
bt_assert(p.evpn_tag = 220);
|
||||||
|
bt_assert(p.mac = 12:a6:54:da:bc:bf);
|
||||||
|
bt_assert(p.ip = ::);
|
||||||
|
|
||||||
|
p = evpn mac 10:1020 224 16:c2:8d:50:86:c5 192.0.2.10;
|
||||||
|
bt_assert(format(p) = "evpn mac 10:1020 224 16:c2:8d:50:86:c5 192.0.2.10");
|
||||||
|
bt_assert(p.type = NET_EVPN);
|
||||||
|
bt_assert(p.evpn_type = NET_EVPN_MAC);
|
||||||
|
bt_assert(p.rd = 10:1020);
|
||||||
|
bt_assert(p.evpn_tag = 224);
|
||||||
|
bt_assert(p.mac = 16:c2:8d:50:86:c5);
|
||||||
|
bt_assert(p.ip = 192.0.2.10);
|
||||||
|
|
||||||
|
p = evpn mac 10:1020 226 2a:3b:24:3d:f0:a0 2001:db8:10:20::1;
|
||||||
|
bt_assert(format(p) = "evpn mac 10:1020 226 2a:3b:24:3d:f0:a0 2001:db8:10:20::1");
|
||||||
|
bt_assert(p.type = NET_EVPN);
|
||||||
|
bt_assert(p.evpn_type = NET_EVPN_MAC);
|
||||||
|
bt_assert(p.rd = 10:1020);
|
||||||
|
bt_assert(p.evpn_tag = 226);
|
||||||
|
bt_assert(p.mac = 2a:3b:24:3d:f0:a0);
|
||||||
|
bt_assert(p.ip = 2001:db8:10:20::1);
|
||||||
|
|
||||||
|
p = evpn imet 10:1030 234 192.0.2.20;
|
||||||
|
bt_assert(format(p) = "evpn imet 10:1030 234 192.0.2.20");
|
||||||
|
bt_assert(p.type = NET_EVPN);
|
||||||
|
bt_assert(p.evpn_type = NET_EVPN_IMET);
|
||||||
|
bt_assert(p.rd = 10:1030);
|
||||||
|
bt_assert(p.evpn_tag = 234);
|
||||||
|
bt_assert(p.router_ip = 192.0.2.20);
|
||||||
|
|
||||||
|
p = evpn imet 10:1030 236 2001:db8:10:20::2;
|
||||||
|
bt_assert(format(p) = "evpn imet 10:1030 236 2001:db8:10:20::2");
|
||||||
|
bt_assert(p.type = NET_EVPN);
|
||||||
|
bt_assert(p.evpn_type = NET_EVPN_IMET);
|
||||||
|
bt_assert(p.rd = 10:1030);
|
||||||
|
bt_assert(p.evpn_tag = 236);
|
||||||
|
bt_assert(p.router_ip = 2001:db8:10:20::2);
|
||||||
|
|
||||||
|
p = evpn es 10:1040 00:10:20:30:40:50:60:70:80:90 192.0.2.40;
|
||||||
|
bt_assert(format(p) = "evpn es 10:1040 00:10:20:30:40:50:60:70:80:90 192.0.2.40");
|
||||||
|
bt_assert(p.type = NET_EVPN);
|
||||||
|
bt_assert(p.evpn_type = NET_EVPN_ES);
|
||||||
|
bt_assert(p.rd = 10:1040);
|
||||||
|
bt_assert(p.evpn_esi = 00:10:20:30:40:50:60:70:80:90);
|
||||||
|
bt_assert(p.router_ip = 192.0.2.40);
|
||||||
|
}
|
||||||
|
|
||||||
|
bt_test_suite(t_net_evpn, "Testing EVPN nets");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Testing defined() function
|
* Testing defined() function
|
||||||
* --------------------------
|
* --------------------------
|
||||||
|
@ -540,6 +540,9 @@ aggregator_rt_notify(struct proto *P, struct channel *src_ch, net *net, rte *new
|
|||||||
case T_IP:
|
case T_IP:
|
||||||
MX(ip);
|
MX(ip);
|
||||||
break;
|
break;
|
||||||
|
case T_MAC:
|
||||||
|
MX(mac);
|
||||||
|
break;
|
||||||
case T_NET:
|
case T_NET:
|
||||||
mem_hash_mix_num(&haux, net_hash(IT(net)));
|
mem_hash_mix_num(&haux, net_hash(IT(net)));
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user