mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2025-03-21 22:07:03 +00:00
Nest: Use rtable for neighbor lookup
Implicitly define rtables 'local4' and 'local6' and a pair of direct protocols to fill them. Use modified net_route() for neighbor lookup to avoid iterating over all interfaces.
This commit is contained in:
parent
7d1c2ea5c0
commit
3d23e41dcb
@ -30,6 +30,8 @@ struct config {
|
|||||||
char *syslog_name; /* Name used for syslog (NULL -> no syslog) */
|
char *syslog_name; /* Name used for syslog (NULL -> no syslog) */
|
||||||
struct rtable_config *def_tables[NET_MAX]; /* Default routing tables for each network */
|
struct rtable_config *def_tables[NET_MAX]; /* Default routing tables for each network */
|
||||||
struct iface_patt *router_id_from; /* Configured list of router ID iface patterns */
|
struct iface_patt *router_id_from; /* Configured list of router ID iface patterns */
|
||||||
|
struct rtable_config *local4;
|
||||||
|
struct rtable_config *local6;
|
||||||
|
|
||||||
u32 router_id; /* Our Router ID */
|
u32 router_id; /* Our Router ID */
|
||||||
unsigned proto_default_debug; /* Default protocol debug mask */
|
unsigned proto_default_debug; /* Default protocol debug mask */
|
||||||
|
@ -74,7 +74,7 @@ CF_KEYWORDS(PRIMARY, STATS, COUNT, BY, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENER
|
|||||||
CF_KEYWORDS(BGP, PASSWORDS, DESCRIPTION, SORTED, ORDERED)
|
CF_KEYWORDS(BGP, PASSWORDS, DESCRIPTION, SORTED, ORDERED)
|
||||||
CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC, CLASS, DSCP)
|
CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC, CLASS, DSCP)
|
||||||
CF_KEYWORDS(TIMEFORMAT, ISO, SHORT, LONG, ROUTE, PROTOCOL, BASE, LOG, S, MS, US)
|
CF_KEYWORDS(TIMEFORMAT, ISO, SHORT, LONG, ROUTE, PROTOCOL, BASE, LOG, S, MS, US)
|
||||||
CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS, STATISTICS)
|
CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS, STATISTICS, NETWORKS, ADDRESSES)
|
||||||
|
|
||||||
/* For r_args_channel */
|
/* For r_args_channel */
|
||||||
CF_KEYWORDS(IPV4, IPV4_MC, IPV4_MPLS, IPV6, IPV6_MC, IPV6_MPLS, IPV6_SADR, VPN4, VPN4_MC, VPN4_MPLS, VPN6, VPN6_MC, VPN6_MPLS, ROA4, ROA6, FLOW4, FLOW6, MPLS, PRI, SEC)
|
CF_KEYWORDS(IPV4, IPV4_MC, IPV4_MPLS, IPV6, IPV6_MC, IPV6_MPLS, IPV6_SADR, VPN4, VPN4_MC, VPN4_MPLS, VPN6, VPN6_MC, VPN6_MPLS, ROA4, ROA6, FLOW4, FLOW6, MPLS, PRI, SEC)
|
||||||
|
@ -122,6 +122,8 @@ neigh_find(struct proto *p, ip_addr *a, unsigned flags)
|
|||||||
return neigh_find2(p, a, NULL, flags);
|
return neigh_find2(p, a, NULL, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct iface * net_route_ifa(const ip_addr *a, struct iface *vrf);
|
||||||
|
|
||||||
|
|
||||||
neighbor *
|
neighbor *
|
||||||
neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags)
|
neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags)
|
||||||
@ -153,13 +155,11 @@ neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags)
|
|||||||
scope = class & IADDR_SCOPE_MASK;
|
scope = class & IADDR_SCOPE_MASK;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
WALK_LIST(i, iface_list)
|
{
|
||||||
if ((!p->vrf || p->vrf == i->master) &&
|
if ((i = net_route_ifa(a, p->vrf)) &&
|
||||||
((scope = if_connected(a, i, &addr)) >= 0))
|
((scope = if_connected(a, i, &addr)) >= 0))
|
||||||
{
|
ifa = i;
|
||||||
ifa = i;
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* scope < 0 means i don't know neighbor */
|
/* scope < 0 means i don't know neighbor */
|
||||||
/* scope >= 0 implies ifa != NULL */
|
/* scope >= 0 implies ifa != NULL */
|
||||||
|
13
nest/proto.c
13
nest/proto.c
@ -737,6 +737,7 @@ proto_new(struct proto_config *cf)
|
|||||||
p->proto = cf->protocol;
|
p->proto = cf->protocol;
|
||||||
p->net_type = cf->net_type;
|
p->net_type = cf->net_type;
|
||||||
p->disabled = cf->disabled;
|
p->disabled = cf->disabled;
|
||||||
|
p->hidden = cf->hidden;
|
||||||
p->hash_key = random_u32();
|
p->hash_key = random_u32();
|
||||||
cf->proto = p;
|
cf->proto = p;
|
||||||
|
|
||||||
@ -1025,7 +1026,13 @@ protos_commit(struct config *new, struct config *old, int force_reconfig, int ty
|
|||||||
|
|
||||||
DBG("Protocol start\n");
|
DBG("Protocol start\n");
|
||||||
|
|
||||||
/* Start device protocol first */
|
|
||||||
|
/* Start direct protocols first */
|
||||||
|
WALK_LIST_DELSAFE(p, n, proto_list)
|
||||||
|
if (p->proto == &proto_device)
|
||||||
|
proto_rethink_goal(p);
|
||||||
|
|
||||||
|
/* Start device protocol second */
|
||||||
if (first_dev_proto)
|
if (first_dev_proto)
|
||||||
proto_rethink_goal(first_dev_proto);
|
proto_rethink_goal(first_dev_proto);
|
||||||
|
|
||||||
@ -1903,7 +1910,7 @@ proto_apply_cmd_patt(char *patt, void (* cmd)(struct proto *, uintptr_t, int), u
|
|||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
|
|
||||||
WALK_LIST(p, proto_list)
|
WALK_LIST(p, proto_list)
|
||||||
if (!patt || patmatch(patt, p->name))
|
if ((!patt || patmatch(patt, p->name)) && !p->hidden)
|
||||||
cmd(p, arg, cnt++);
|
cmd(p, arg, cnt++);
|
||||||
|
|
||||||
if (!cnt)
|
if (!cnt)
|
||||||
@ -1943,7 +1950,7 @@ proto_get_named(struct symbol *sym, struct protocol *pr)
|
|||||||
{
|
{
|
||||||
p = NULL;
|
p = NULL;
|
||||||
WALK_LIST(q, proto_list)
|
WALK_LIST(q, proto_list)
|
||||||
if ((q->proto == pr) && (q->proto_state != PS_DOWN))
|
if ((q->proto == pr) && (q->proto_state != PS_DOWN) && !q->hidden)
|
||||||
{
|
{
|
||||||
if (p)
|
if (p)
|
||||||
cf_error("There are multiple %s protocols running", pr->name);
|
cf_error("There are multiple %s protocols running", pr->name);
|
||||||
|
@ -96,6 +96,7 @@ struct proto_config {
|
|||||||
int class; /* SYM_PROTO or SYM_TEMPLATE */
|
int class; /* SYM_PROTO or SYM_TEMPLATE */
|
||||||
u8 net_type; /* Protocol network type (NET_*), 0 for undefined */
|
u8 net_type; /* Protocol network type (NET_*), 0 for undefined */
|
||||||
u8 disabled; /* Protocol enabled/disabled by default */
|
u8 disabled; /* Protocol enabled/disabled by default */
|
||||||
|
byte hidden; /* Protocol not showed in show protocols */
|
||||||
u32 debug, mrtdump; /* Debugging bitfields, both use D_* constants */
|
u32 debug, mrtdump; /* Debugging bitfields, both use D_* constants */
|
||||||
u32 router_id; /* Protocol specific router ID */
|
u32 router_id; /* Protocol specific router ID */
|
||||||
|
|
||||||
@ -160,6 +161,7 @@ struct proto {
|
|||||||
byte gr_recovery; /* Protocol should participate in graceful restart recovery */
|
byte gr_recovery; /* Protocol should participate in graceful restart recovery */
|
||||||
byte down_sched; /* Shutdown is scheduled for later (PDS_*) */
|
byte down_sched; /* Shutdown is scheduled for later (PDS_*) */
|
||||||
byte down_code; /* Reason for shutdown (PDC_* codes) */
|
byte down_code; /* Reason for shutdown (PDC_* codes) */
|
||||||
|
byte hidden; /* Protocol not showed in show protocols */
|
||||||
u32 hash_key; /* Random key used for hashing of neighbors */
|
u32 hash_key; /* Random key used for hashing of neighbors */
|
||||||
btime last_state_change; /* Time of last state transition */
|
btime last_state_change; /* Time of last state transition */
|
||||||
char *last_state_name_announced; /* Last state name we've announced to the user */
|
char *last_state_name_announced; /* Last state name we've announced to the user */
|
||||||
|
@ -54,6 +54,12 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad)
|
|||||||
if (!c)
|
if (!c)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (cf->host_ip)
|
||||||
|
{
|
||||||
|
net = alloca(sizeof(net_addr));
|
||||||
|
net_fill_ip_host(net, ad->ip);
|
||||||
|
}
|
||||||
|
|
||||||
/* For IPv6 SADR, replace regular prefix with SADR prefix */
|
/* For IPv6 SADR, replace regular prefix with SADR prefix */
|
||||||
if (c->net_type == NET_IP6_SADR)
|
if (c->net_type == NET_IP6_SADR)
|
||||||
{
|
{
|
||||||
|
@ -13,6 +13,7 @@ struct rt_dev_config {
|
|||||||
struct proto_config c;
|
struct proto_config c;
|
||||||
list iface_list; /* list of struct iface_patt */
|
list iface_list; /* list of struct iface_patt */
|
||||||
int check_link;
|
int check_link;
|
||||||
|
int host_ip; /* Annunce local IP instead of prefix */
|
||||||
|
|
||||||
struct channel_config *ip4_channel;
|
struct channel_config *ip4_channel;
|
||||||
struct channel_config *ip6_channel;
|
struct channel_config *ip6_channel;
|
||||||
|
126
nest/rt-table.c
126
nest/rt-table.c
@ -34,6 +34,7 @@
|
|||||||
#include "nest/route.h"
|
#include "nest/route.h"
|
||||||
#include "nest/protocol.h"
|
#include "nest/protocol.h"
|
||||||
#include "nest/iface.h"
|
#include "nest/iface.h"
|
||||||
|
#include "nest/rt-dev.h"
|
||||||
#include "nest/cli.h"
|
#include "nest/cli.h"
|
||||||
#include "lib/resource.h"
|
#include "lib/resource.h"
|
||||||
#include "lib/event.h"
|
#include "lib/event.h"
|
||||||
@ -171,6 +172,87 @@ net_route(rtable *tab, const net_addr *n)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct iface *
|
||||||
|
net_route_ifa4(rtable *t, net_addr_ip4 *a, struct iface *vrf)
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (!BIT32_TEST(t->pxlens, a->pxlen))
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
net *n = net_find(t, (net_addr *) a);
|
||||||
|
|
||||||
|
if (!n)
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
for (rte *e = n->routes; e; e = e->next)
|
||||||
|
{
|
||||||
|
struct iface *i = e->attrs->nh.iface;
|
||||||
|
if (rte_is_valid(e) &&
|
||||||
|
(e->attrs->dest == RTD_UNICAST) &&
|
||||||
|
(!vrf || vrf == i->master))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
next:
|
||||||
|
if (!a->pxlen)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
a->pxlen--;
|
||||||
|
ip4_clrbit(&a->prefix, a->pxlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct iface *
|
||||||
|
net_route_ifa6(rtable *t, net_addr_ip6 *a, struct iface *vrf)
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (!BIT32_TEST(t->pxlens, a->pxlen))
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
net *n = net_find(t, (net_addr *) a);
|
||||||
|
|
||||||
|
if (!n)
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
for (rte *e = n->routes; e; e = e->next)
|
||||||
|
{
|
||||||
|
struct iface *i = e->attrs->nh.iface;
|
||||||
|
if (rte_is_valid(e) &&
|
||||||
|
(e->attrs->dest == RTD_UNICAST) &&
|
||||||
|
(!vrf || vrf == i->master))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
next:
|
||||||
|
if (!a->pxlen)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
a->pxlen--;
|
||||||
|
ip6_clrbit(&a->prefix, a->pxlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct iface *
|
||||||
|
net_route_ifa(const ip_addr *a, struct iface *vrf)
|
||||||
|
{
|
||||||
|
net_addr n0;
|
||||||
|
net_fill_ip_host(&n0, *a);
|
||||||
|
|
||||||
|
switch (n0.type)
|
||||||
|
{
|
||||||
|
case NET_IP4:
|
||||||
|
return net_route_ifa4(config->local4->table, (net_addr_ip4 *) &n0, vrf);
|
||||||
|
|
||||||
|
case NET_IP6:
|
||||||
|
return net_route_ifa6(config->local6->table, (net_addr_ip6 *) &n0, vrf);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
net_roa_check_ip4(rtable *tab, const net_addr_ip4 *px, u32 asn)
|
net_roa_check_ip4(rtable *tab, const net_addr_ip4 *px, u32 asn)
|
||||||
@ -1821,6 +1903,50 @@ rt_preconfig(struct config *c)
|
|||||||
|
|
||||||
rt_new_table(cf_get_symbol("master4"), NET_IP4);
|
rt_new_table(cf_get_symbol("master4"), NET_IP4);
|
||||||
rt_new_table(cf_get_symbol("master6"), NET_IP6);
|
rt_new_table(cf_get_symbol("master6"), NET_IP6);
|
||||||
|
|
||||||
|
c->local4 = rt_new_table(cf_get_symbol("local4"), NET_IP4);
|
||||||
|
c->local6 = rt_new_table(cf_get_symbol("local6"), NET_IP6);
|
||||||
|
|
||||||
|
|
||||||
|
/* Define two direct protocols and connect them to local tables */
|
||||||
|
|
||||||
|
struct symbol *s;
|
||||||
|
struct rt_dev_config *dev;
|
||||||
|
static struct channel_config *cc;
|
||||||
|
|
||||||
|
s = cf_get_symbol("networks");
|
||||||
|
dev = proto_config_new(&proto_device, SYM_PROTO);
|
||||||
|
init_list(&dev->iface_list);
|
||||||
|
cf_define_symbol(s, SYM_PROTO, dev);
|
||||||
|
dev->c.name = s->name;
|
||||||
|
dev->c.hidden = 1;
|
||||||
|
// dev->c.debug = D_EVENTS | D_STATES | D_IFACES;
|
||||||
|
|
||||||
|
cc = channel_config_get(NULL, net_label[NET_IP4], NET_IP4, &dev->c);
|
||||||
|
cc->table = c->local4;
|
||||||
|
|
||||||
|
cc = channel_config_get(NULL, net_label[NET_IP6], NET_IP6, &dev->c);
|
||||||
|
cc->table = c->local6;
|
||||||
|
|
||||||
|
proto_device.postconfig(&dev->c);
|
||||||
|
|
||||||
|
|
||||||
|
s = cf_get_symbol("addresses");
|
||||||
|
dev = proto_config_new(&proto_device, SYM_PROTO);
|
||||||
|
init_list(&dev->iface_list);
|
||||||
|
cf_define_symbol(s, SYM_PROTO, dev);
|
||||||
|
dev->c.name = s->name;
|
||||||
|
dev->c.hidden = 1;
|
||||||
|
// dev->c.debug = D_EVENTS | D_STATES | D_IFACES;
|
||||||
|
dev->host_ip = 1;
|
||||||
|
|
||||||
|
cc = channel_config_get(NULL, net_label[NET_IP4], NET_IP4, &dev->c);
|
||||||
|
cc->table = c->local4;
|
||||||
|
|
||||||
|
cc = channel_config_get(NULL, net_label[NET_IP6], NET_IP6, &dev->c);
|
||||||
|
cc->table = c->local6;
|
||||||
|
|
||||||
|
proto_device.postconfig(&dev->c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user