Merge commit 'e42eedb9' into haugesund
This commit is contained in:
commit
24773af9e0
20 changed files with 246 additions and 302 deletions
|
@ -1747,7 +1747,7 @@ Common route attributes are:
|
||||||
|
|
||||||
<tag><label id="rta-source"><m/enum/ source</tag>
|
<tag><label id="rta-source"><m/enum/ source</tag>
|
||||||
what protocol has told me about this route. Possible values:
|
what protocol has told me about this route. Possible values:
|
||||||
<cf/RTS_DUMMY/, <cf/RTS_STATIC/, <cf/RTS_INHERIT/, <cf/RTS_DEVICE/,
|
<cf/RTS_STATIC/, <cf/RTS_INHERIT/, <cf/RTS_DEVICE/,
|
||||||
<cf/RTS_RIP/, <cf/RTS_OSPF/, <cf/RTS_OSPF_IA/, <cf/RTS_OSPF_EXT1/,
|
<cf/RTS_RIP/, <cf/RTS_OSPF/, <cf/RTS_OSPF_IA/, <cf/RTS_OSPF_EXT1/,
|
||||||
<cf/RTS_OSPF_EXT2/, <cf/RTS_BGP/, <cf/RTS_PIPE/, <cf/RTS_BABEL/.
|
<cf/RTS_OSPF_EXT2/, <cf/RTS_BGP/, <cf/RTS_PIPE/, <cf/RTS_BABEL/.
|
||||||
|
|
||||||
|
|
|
@ -398,7 +398,6 @@ bt_test_suite(t_ip_set, "Testing sets of ip address");
|
||||||
|
|
||||||
function t_enum()
|
function t_enum()
|
||||||
{
|
{
|
||||||
bt_assert(format(RTS_DUMMY) = "(enum 30)0");
|
|
||||||
bt_assert(format(RTS_STATIC) = "(enum 30)1");
|
bt_assert(format(RTS_STATIC) = "(enum 30)1");
|
||||||
bt_assert(format(NET_IP4) = "(enum 36)1");
|
bt_assert(format(NET_IP4) = "(enum 36)1");
|
||||||
bt_assert(format(NET_VPN6) = "(enum 36)4");
|
bt_assert(format(NET_VPN6) = "(enum 36)4");
|
||||||
|
|
|
@ -130,7 +130,7 @@ CF_KEYWORDS(SORTED, TRIE, MIN, MAX, SETTLE, TIME)
|
||||||
/* 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)
|
||||||
|
|
||||||
CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT,
|
CF_ENUM(T_ENUM_RTS, RTS_, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT,
|
||||||
RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE, BABEL)
|
RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE, BABEL)
|
||||||
CF_ENUM(T_ENUM_SCOPE, SCOPE_, HOST, LINK, SITE, ORGANIZATION, UNIVERSE, UNDEFINED)
|
CF_ENUM(T_ENUM_SCOPE, SCOPE_, HOST, LINK, SITE, ORGANIZATION, UNIVERSE, UNDEFINED)
|
||||||
CF_ENUM(T_ENUM_RTD, RTD_, UNICAST, BLACKHOLE, UNREACHABLE, PROHIBIT)
|
CF_ENUM(T_ENUM_RTD, RTD_, UNICAST, BLACKHOLE, UNREACHABLE, PROHIBIT)
|
||||||
|
|
|
@ -241,6 +241,7 @@ struct proto {
|
||||||
struct rte * (*rte_modify)(struct rte *, struct linpool *);
|
struct rte * (*rte_modify)(struct rte *, struct linpool *);
|
||||||
void (*rte_insert)(struct network *, struct rte *);
|
void (*rte_insert)(struct network *, struct rte *);
|
||||||
void (*rte_remove)(struct network *, struct rte *);
|
void (*rte_remove)(struct network *, struct rte *);
|
||||||
|
u32 (*rte_igp_metric)(struct rte *);
|
||||||
|
|
||||||
/* Hic sunt protocol-specific data */
|
/* Hic sunt protocol-specific data */
|
||||||
};
|
};
|
||||||
|
|
36
nest/route.h
36
nest/route.h
|
@ -263,20 +263,6 @@ typedef struct rte {
|
||||||
byte pflags; /* Protocol-specific flags */
|
byte pflags; /* Protocol-specific flags */
|
||||||
btime lastmod; /* Last modified */
|
btime lastmod; /* Last modified */
|
||||||
union { /* Protocol-dependent data (metrics etc.) */
|
union { /* Protocol-dependent data (metrics etc.) */
|
||||||
#ifdef CONFIG_RIP
|
|
||||||
struct {
|
|
||||||
struct iface *from; /* Incoming iface */
|
|
||||||
u8 metric; /* RIP metric */
|
|
||||||
u16 tag; /* External route tag */
|
|
||||||
} rip;
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_OSPF
|
|
||||||
struct {
|
|
||||||
u32 metric1, metric2; /* OSPF Type 1 and Type 2 metrics */
|
|
||||||
u32 tag; /* External route tag */
|
|
||||||
u32 router_id; /* Router that originated this route */
|
|
||||||
} ospf;
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_BGP
|
#ifdef CONFIG_BGP
|
||||||
struct {
|
struct {
|
||||||
u8 suppressed; /* Used for deterministic MED comparison */
|
u8 suppressed; /* Used for deterministic MED comparison */
|
||||||
|
@ -284,20 +270,6 @@ typedef struct rte {
|
||||||
struct rtable *base_table; /* Base table for Flowspec validation */
|
struct rtable *base_table; /* Base table for Flowspec validation */
|
||||||
} bgp;
|
} bgp;
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_BABEL
|
|
||||||
struct {
|
|
||||||
u16 seqno; /* Babel seqno */
|
|
||||||
u16 metric; /* Babel metric */
|
|
||||||
u64 router_id; /* Babel router id */
|
|
||||||
} babel;
|
|
||||||
#endif
|
|
||||||
struct { /* Routes generated by krt sync (both temporary and inherited ones) */
|
|
||||||
s8 src; /* Alleged route source (see krt.h) */
|
|
||||||
u8 proto; /* Kernel source protocol ID */
|
|
||||||
u8 seen; /* Seen during last scan */
|
|
||||||
u8 best; /* Best route in network, propagated to core */
|
|
||||||
u32 metric; /* Kernel metric */
|
|
||||||
} krt;
|
|
||||||
} u;
|
} u;
|
||||||
} rte;
|
} rte;
|
||||||
|
|
||||||
|
@ -498,7 +470,6 @@ typedef struct rta {
|
||||||
struct nexthop nh; /* Next hop */
|
struct nexthop nh; /* Next hop */
|
||||||
} rta;
|
} rta;
|
||||||
|
|
||||||
#define RTS_DUMMY 0 /* Dummy route to be removed soon */
|
|
||||||
#define RTS_STATIC 1 /* Normal static route */
|
#define RTS_STATIC 1 /* Normal static route */
|
||||||
#define RTS_INHERIT 2 /* Route inherited from kernel */
|
#define RTS_INHERIT 2 /* Route inherited from kernel */
|
||||||
#define RTS_DEVICE 3 /* Device route */
|
#define RTS_DEVICE 3 /* Device route */
|
||||||
|
@ -546,8 +517,8 @@ typedef struct eattr {
|
||||||
byte flags; /* Protocol-dependent flags */
|
byte flags; /* Protocol-dependent flags */
|
||||||
byte type; /* Attribute type and several flags (EAF_...) */
|
byte type; /* Attribute type and several flags (EAF_...) */
|
||||||
union {
|
union {
|
||||||
u32 data;
|
uintptr_t data;
|
||||||
const struct adata *ptr; /* Attribute data elsewhere */
|
const struct adata *ptr; /* Attribute data elsewhere */
|
||||||
} u;
|
} u;
|
||||||
} eattr;
|
} eattr;
|
||||||
|
|
||||||
|
@ -578,6 +549,7 @@ const char *ea_custom_name(uint ea);
|
||||||
#define EAF_TYPE_AS_PATH 0x06 /* BGP AS path (encoding per RFC 1771:4.3) */
|
#define EAF_TYPE_AS_PATH 0x06 /* BGP AS path (encoding per RFC 1771:4.3) */
|
||||||
#define EAF_TYPE_BITFIELD 0x09 /* 32-bit embedded bitfield */
|
#define EAF_TYPE_BITFIELD 0x09 /* 32-bit embedded bitfield */
|
||||||
#define EAF_TYPE_INT_SET 0x0a /* Set of u32's (e.g., a community list) */
|
#define EAF_TYPE_INT_SET 0x0a /* Set of u32's (e.g., a community list) */
|
||||||
|
#define EAF_TYPE_PTR 0x0d /* Pointer to an object */
|
||||||
#define EAF_TYPE_EC_SET 0x0e /* Set of pairs of u32's - ext. community list */
|
#define EAF_TYPE_EC_SET 0x0e /* Set of pairs of u32's - ext. community list */
|
||||||
#define EAF_TYPE_LC_SET 0x12 /* Set of triplets of u32's - large community list */
|
#define EAF_TYPE_LC_SET 0x12 /* Set of triplets of u32's - large community list */
|
||||||
#define EAF_TYPE_UNDEF 0x1f /* `force undefined' entry */
|
#define EAF_TYPE_UNDEF 0x1f /* `force undefined' entry */
|
||||||
|
@ -632,7 +604,7 @@ struct ea_walk_state {
|
||||||
|
|
||||||
eattr *ea_find(ea_list *, unsigned ea);
|
eattr *ea_find(ea_list *, unsigned ea);
|
||||||
eattr *ea_walk(struct ea_walk_state *s, uint id, uint max);
|
eattr *ea_walk(struct ea_walk_state *s, uint id, uint max);
|
||||||
int ea_get_int(ea_list *, unsigned ea, int def);
|
uintptr_t ea_get_int(ea_list *, unsigned ea, uintptr_t def);
|
||||||
void ea_dump(ea_list *);
|
void ea_dump(ea_list *);
|
||||||
void ea_sort(ea_list *); /* Sort entries in all sub-lists */
|
void ea_sort(ea_list *); /* Sort entries in all sub-lists */
|
||||||
unsigned ea_scan(ea_list *); /* How many bytes do we need for merged ea_list */
|
unsigned ea_scan(ea_list *); /* How many bytes do we need for merged ea_list */
|
||||||
|
|
|
@ -61,7 +61,6 @@
|
||||||
const adata null_adata; /* adata of length 0 */
|
const adata null_adata; /* adata of length 0 */
|
||||||
|
|
||||||
const char * const rta_src_names[RTS_MAX] = {
|
const char * const rta_src_names[RTS_MAX] = {
|
||||||
[RTS_DUMMY] = "",
|
|
||||||
[RTS_STATIC] = "static",
|
[RTS_STATIC] = "static",
|
||||||
[RTS_INHERIT] = "inherit",
|
[RTS_INHERIT] = "inherit",
|
||||||
[RTS_DEVICE] = "device",
|
[RTS_DEVICE] = "device",
|
||||||
|
@ -541,8 +540,8 @@ ea_walk(struct ea_walk_state *s, uint id, uint max)
|
||||||
* by calling ea_find() to find the attribute, extracting its value or returning
|
* by calling ea_find() to find the attribute, extracting its value or returning
|
||||||
* a provided default if no such attribute is present.
|
* a provided default if no such attribute is present.
|
||||||
*/
|
*/
|
||||||
int
|
uintptr_t
|
||||||
ea_get_int(ea_list *e, unsigned id, int def)
|
ea_get_int(ea_list *e, unsigned id, uintptr_t def)
|
||||||
{
|
{
|
||||||
eattr *a = ea_find(e, id);
|
eattr *a = ea_find(e, id);
|
||||||
if (!a)
|
if (!a)
|
||||||
|
@ -1260,7 +1259,7 @@ rta_do_cow(rta *o, linpool *lp)
|
||||||
void
|
void
|
||||||
rta_dump(rta *a)
|
rta_dump(rta *a)
|
||||||
{
|
{
|
||||||
static char *rts[] = { "RTS_DUMMY", "RTS_STATIC", "RTS_INHERIT", "RTS_DEVICE",
|
static char *rts[] = { "", "RTS_STATIC", "RTS_INHERIT", "RTS_DEVICE",
|
||||||
"RTS_STAT_DEV", "RTS_REDIR", "RTS_RIP",
|
"RTS_STAT_DEV", "RTS_REDIR", "RTS_RIP",
|
||||||
"RTS_OSPF", "RTS_OSPF_IA", "RTS_OSPF_EXT1",
|
"RTS_OSPF", "RTS_OSPF_IA", "RTS_OSPF_EXT1",
|
||||||
"RTS_OSPF_EXT2", "RTS_BGP", "RTS_PIPE", "RTS_BABEL" };
|
"RTS_OSPF_EXT2", "RTS_BGP", "RTS_PIPE", "RTS_BABEL" };
|
||||||
|
|
|
@ -1686,26 +1686,6 @@ rte_update_unlock(void)
|
||||||
lp_flush(rte_update_pool);
|
lp_flush(rte_update_pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
|
||||||
rte_hide_dummy_routes(net *net, rte **dummy)
|
|
||||||
{
|
|
||||||
if (net->routes && net->routes->attrs->source == RTS_DUMMY)
|
|
||||||
{
|
|
||||||
*dummy = net->routes;
|
|
||||||
net->routes = (*dummy)->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
rte_unhide_dummy_routes(net *net, rte **dummy)
|
|
||||||
{
|
|
||||||
if (*dummy)
|
|
||||||
{
|
|
||||||
(*dummy)->next = net->routes;
|
|
||||||
net->routes = *dummy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rte_update - enter a new update to a routing table
|
* rte_update - enter a new update to a routing table
|
||||||
* @table: table to be updated
|
* @table: table to be updated
|
||||||
|
@ -1754,7 +1734,6 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
|
||||||
// struct proto *p = c->proto;
|
// struct proto *p = c->proto;
|
||||||
struct proto_stats *stats = &c->stats;
|
struct proto_stats *stats = &c->stats;
|
||||||
const struct filter *filter = c->in_filter;
|
const struct filter *filter = c->in_filter;
|
||||||
rte *dummy = NULL;
|
|
||||||
net *nn;
|
net *nn;
|
||||||
|
|
||||||
ASSERT(c->channel_state == CS_UP);
|
ASSERT(c->channel_state == CS_UP);
|
||||||
|
@ -1833,9 +1812,7 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
|
||||||
|
|
||||||
recalc:
|
recalc:
|
||||||
/* And recalculate the best route */
|
/* And recalculate the best route */
|
||||||
rte_hide_dummy_routes(nn, &dummy);
|
|
||||||
rte_recalculate(c, nn, new, src);
|
rte_recalculate(c, nn, new, src);
|
||||||
rte_unhide_dummy_routes(nn, &dummy);
|
|
||||||
|
|
||||||
rte_update_unlock();
|
rte_update_unlock();
|
||||||
return;
|
return;
|
||||||
|
@ -3686,36 +3663,12 @@ rt_get_igp_metric(rte *rt)
|
||||||
if (ea)
|
if (ea)
|
||||||
return ea->u.data;
|
return ea->u.data;
|
||||||
|
|
||||||
rta *a = rt->attrs;
|
if (rt->attrs->source == RTS_DEVICE)
|
||||||
|
|
||||||
#ifdef CONFIG_OSPF
|
|
||||||
if ((a->source == RTS_OSPF) ||
|
|
||||||
(a->source == RTS_OSPF_IA) ||
|
|
||||||
(a->source == RTS_OSPF_EXT1))
|
|
||||||
return rt->u.ospf.metric1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_RIP
|
|
||||||
if (a->source == RTS_RIP)
|
|
||||||
return rt->u.rip.metric;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_BGP
|
|
||||||
if (a->source == RTS_BGP)
|
|
||||||
{
|
|
||||||
u64 metric = bgp_total_aigp_metric(rt);
|
|
||||||
return (u32) MIN(metric, (u64) IGP_METRIC_UNKNOWN);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_BABEL
|
|
||||||
if (a->source == RTS_BABEL)
|
|
||||||
return rt->u.babel.metric;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (a->source == RTS_DEVICE)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (rt->src->proto->rte_igp_metric)
|
||||||
|
return rt->src->proto->rte_igp_metric(rt);
|
||||||
|
|
||||||
return IGP_METRIC_UNKNOWN;
|
return IGP_METRIC_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -648,6 +648,29 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e)
|
||||||
.from = r->neigh->addr,
|
.from = r->neigh->addr,
|
||||||
.nh.gw = r->next_hop,
|
.nh.gw = r->next_hop,
|
||||||
.nh.iface = r->neigh->ifa->iface,
|
.nh.iface = r->neigh->ifa->iface,
|
||||||
|
.eattrs = alloca(sizeof(ea_list) + 3*sizeof(eattr)),
|
||||||
|
};
|
||||||
|
|
||||||
|
*a0.eattrs = (ea_list) { .count = 3 };
|
||||||
|
a0.eattrs->attrs[0] = (eattr) {
|
||||||
|
.id = EA_BABEL_METRIC,
|
||||||
|
.type = EAF_TYPE_INT,
|
||||||
|
.u.data = r->metric,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct adata *ad = alloca(sizeof(struct adata) + sizeof(u64));
|
||||||
|
ad->length = sizeof(u64);
|
||||||
|
memcpy(ad->data, &(r->router_id), sizeof(u64));
|
||||||
|
a0.eattrs->attrs[1] = (eattr) {
|
||||||
|
.id = EA_BABEL_ROUTER_ID,
|
||||||
|
.type = EAF_TYPE_OPAQUE,
|
||||||
|
.u.ptr = ad,
|
||||||
|
};
|
||||||
|
|
||||||
|
a0.eattrs->attrs[2] = (eattr) {
|
||||||
|
.id = EA_BABEL_SEQNO,
|
||||||
|
.type = EAF_TYPE_INT,
|
||||||
|
.u.data = r->seqno,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -660,10 +683,6 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e)
|
||||||
|
|
||||||
rta *a = rta_lookup(&a0);
|
rta *a = rta_lookup(&a0);
|
||||||
rte *rte = rte_get_temp(a, p->p.main_source);
|
rte *rte = rte_get_temp(a, p->p.main_source);
|
||||||
rte->u.babel.seqno = r->seqno;
|
|
||||||
rte->u.babel.metric = r->metric;
|
|
||||||
rte->u.babel.router_id = r->router_id;
|
|
||||||
rte->pflags = EA_ID_FLAG(EA_BABEL_METRIC) | EA_ID_FLAG(EA_BABEL_ROUTER_ID);
|
|
||||||
|
|
||||||
e->unreachable = 0;
|
e->unreachable = 0;
|
||||||
rte_update2(c, e->n.addr, rte, p->p.main_source);
|
rte_update2(c, e->n.addr, rte, p->p.main_source);
|
||||||
|
@ -680,7 +699,6 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e)
|
||||||
|
|
||||||
rta *a = rta_lookup(&a0);
|
rta *a = rta_lookup(&a0);
|
||||||
rte *rte = rte_get_temp(a, p->p.main_source);
|
rte *rte = rte_get_temp(a, p->p.main_source);
|
||||||
memset(&rte->u.babel, 0, sizeof(rte->u.babel));
|
|
||||||
rte->pflags = 0;
|
rte->pflags = 0;
|
||||||
|
|
||||||
e->unreachable = 1;
|
e->unreachable = 1;
|
||||||
|
@ -2009,7 +2027,13 @@ babel_dump(struct proto *P)
|
||||||
static void
|
static void
|
||||||
babel_get_route_info(rte *rte, byte *buf)
|
babel_get_route_info(rte *rte, byte *buf)
|
||||||
{
|
{
|
||||||
buf += bsprintf(buf, " (%d/%d) [%lR]", rte->attrs->pref, rte->u.babel.metric, rte->u.babel.router_id);
|
u64 rid = 0;
|
||||||
|
eattr *e = ea_find(rte->attrs->eattrs, EA_BABEL_ROUTER_ID);
|
||||||
|
if (e)
|
||||||
|
memcpy(&rid, e->u.ptr->data, sizeof(u64));
|
||||||
|
|
||||||
|
buf += bsprintf(buf, " (%d/%d) [%lR]", rte->attrs->pref,
|
||||||
|
ea_get_int(rte->attrs->eattrs, EA_BABEL_METRIC, BABEL_INFINITY), rid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -2017,6 +2041,9 @@ babel_get_attr(const eattr *a, byte *buf, int buflen UNUSED)
|
||||||
{
|
{
|
||||||
switch (a->id)
|
switch (a->id)
|
||||||
{
|
{
|
||||||
|
case EA_BABEL_SEQNO:
|
||||||
|
return GA_FULL;
|
||||||
|
|
||||||
case EA_BABEL_METRIC:
|
case EA_BABEL_METRIC:
|
||||||
bsprintf(buf, "metric: %d", a->u.data);
|
bsprintf(buf, "metric: %d", a->u.data);
|
||||||
return GA_FULL;
|
return GA_FULL;
|
||||||
|
@ -2240,27 +2267,6 @@ babel_preexport(struct proto *P, struct rte *new)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
babel_make_tmp_attrs(struct rte *rt, struct linpool *pool)
|
|
||||||
{
|
|
||||||
struct adata *id = lp_alloc_adata(pool, sizeof(u64));
|
|
||||||
memcpy(id->data, &rt->u.babel.router_id, sizeof(u64));
|
|
||||||
|
|
||||||
rte_init_tmp_attrs(rt, pool, 2);
|
|
||||||
rte_make_tmp_attr(rt, EA_BABEL_METRIC, EAF_TYPE_INT, rt->u.babel.metric);
|
|
||||||
rte_make_tmp_attr(rt, EA_BABEL_ROUTER_ID, EAF_TYPE_OPAQUE, (uintptr_t) id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
babel_store_tmp_attrs(struct rte *rt, struct linpool *pool)
|
|
||||||
{
|
|
||||||
rte_init_tmp_attrs(rt, pool, 2);
|
|
||||||
rt->u.babel.metric = rte_store_tmp_attr(rt, EA_BABEL_METRIC);
|
|
||||||
|
|
||||||
/* EA_BABEL_ROUTER_ID is read-only, we do not really save the value */
|
|
||||||
rte_store_tmp_attr(rt, EA_BABEL_ROUTER_ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* babel_rt_notify - core tells us about new route (possibly our own),
|
* babel_rt_notify - core tells us about new route (possibly our own),
|
||||||
* so store it into our data structures.
|
* so store it into our data structures.
|
||||||
|
@ -2275,10 +2281,22 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net,
|
||||||
if (new)
|
if (new)
|
||||||
{
|
{
|
||||||
/* Update */
|
/* Update */
|
||||||
uint internal = (new->src->proto == P);
|
uint rt_seqno;
|
||||||
uint rt_seqno = internal ? new->u.babel.seqno : p->update_seqno;
|
|
||||||
uint rt_metric = ea_get_int(new->attrs->eattrs, EA_BABEL_METRIC, 0);
|
uint rt_metric = ea_get_int(new->attrs->eattrs, EA_BABEL_METRIC, 0);
|
||||||
u64 rt_router_id = internal ? new->u.babel.router_id : p->router_id;
|
u64 rt_router_id = 0;
|
||||||
|
|
||||||
|
if (new->src->proto == P)
|
||||||
|
{
|
||||||
|
rt_seqno = ea_find(new->attrs->eattrs, EA_BABEL_SEQNO)->u.data;
|
||||||
|
eattr *e = ea_find(new->attrs->eattrs, EA_BABEL_ROUTER_ID);
|
||||||
|
if (e)
|
||||||
|
memcpy(&rt_router_id, e->u.ptr->data, sizeof(u64));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rt_seqno = p->update_seqno;
|
||||||
|
rt_router_id = p->router_id;
|
||||||
|
}
|
||||||
|
|
||||||
if (rt_metric > BABEL_INFINITY)
|
if (rt_metric > BABEL_INFINITY)
|
||||||
{
|
{
|
||||||
|
@ -2321,15 +2339,16 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net,
|
||||||
static int
|
static int
|
||||||
babel_rte_better(struct rte *new, struct rte *old)
|
babel_rte_better(struct rte *new, struct rte *old)
|
||||||
{
|
{
|
||||||
return new->u.babel.metric < old->u.babel.metric;
|
uint new_metric = ea_find(new->attrs->eattrs, EA_BABEL_SEQNO)->u.data;
|
||||||
|
uint old_metric = ea_find(old->attrs->eattrs, EA_BABEL_SEQNO)->u.data;
|
||||||
|
|
||||||
|
return new_metric < old_metric;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static u32
|
||||||
babel_rte_same(struct rte *new, struct rte *old)
|
babel_rte_igp_metric(struct rte *rt)
|
||||||
{
|
{
|
||||||
return ((new->u.babel.seqno == old->u.babel.seqno) &&
|
return ea_get_int(rt->attrs->eattrs, EA_BABEL_METRIC, BABEL_INFINITY);
|
||||||
(new->u.babel.metric == old->u.babel.metric) &&
|
|
||||||
(new->u.babel.router_id == old->u.babel.router_id));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2363,10 +2382,8 @@ babel_init(struct proto_config *CF)
|
||||||
P->if_notify = babel_if_notify;
|
P->if_notify = babel_if_notify;
|
||||||
P->rt_notify = babel_rt_notify;
|
P->rt_notify = babel_rt_notify;
|
||||||
P->preexport = babel_preexport;
|
P->preexport = babel_preexport;
|
||||||
P->make_tmp_attrs = babel_make_tmp_attrs;
|
|
||||||
P->store_tmp_attrs = babel_store_tmp_attrs;
|
|
||||||
P->rte_better = babel_rte_better;
|
P->rte_better = babel_rte_better;
|
||||||
P->rte_same = babel_rte_same;
|
P->rte_igp_metric = babel_rte_igp_metric;
|
||||||
|
|
||||||
return P;
|
return P;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#define EA_BABEL_METRIC EA_CODE(PROTOCOL_BABEL, 0)
|
#define EA_BABEL_METRIC EA_CODE(PROTOCOL_BABEL, 0)
|
||||||
#define EA_BABEL_ROUTER_ID EA_CODE(PROTOCOL_BABEL, 1)
|
#define EA_BABEL_ROUTER_ID EA_CODE(PROTOCOL_BABEL, 1)
|
||||||
|
#define EA_BABEL_SEQNO EA_CODE(PROTOCOL_BABEL, 2)
|
||||||
|
|
||||||
#define BABEL_MAGIC 42
|
#define BABEL_MAGIC 42
|
||||||
#define BABEL_VERSION 2
|
#define BABEL_VERSION 2
|
||||||
|
|
|
@ -374,6 +374,13 @@ bgp_init_aigp_metric(rte *e, u64 *metric, const struct adata **ad)
|
||||||
return *metric < IGP_METRIC_UNKNOWN;
|
return *metric < IGP_METRIC_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32
|
||||||
|
bgp_rte_igp_metric(struct rte *rt)
|
||||||
|
{
|
||||||
|
u64 metric = bgp_total_aigp_metric(rt);
|
||||||
|
return (u32) MIN(metric, (u64) IGP_METRIC_UNKNOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attribute hooks
|
* Attribute hooks
|
||||||
|
|
|
@ -1679,6 +1679,7 @@ bgp_init(struct proto_config *CF)
|
||||||
P->rte_mergable = bgp_rte_mergable;
|
P->rte_mergable = bgp_rte_mergable;
|
||||||
P->rte_recalculate = cf->deterministic_med ? bgp_rte_recalculate : NULL;
|
P->rte_recalculate = cf->deterministic_med ? bgp_rte_recalculate : NULL;
|
||||||
P->rte_modify = bgp_rte_modify_stale;
|
P->rte_modify = bgp_rte_modify_stale;
|
||||||
|
P->rte_igp_metric = bgp_rte_igp_metric;
|
||||||
|
|
||||||
p->cf = cf;
|
p->cf = cf;
|
||||||
p->is_internal = (cf->local_as == cf->remote_as);
|
p->is_internal = (cf->local_as == cf->remote_as);
|
||||||
|
|
|
@ -584,6 +584,7 @@ int bgp_rte_better(struct rte *, struct rte *);
|
||||||
int bgp_rte_mergable(rte *pri, rte *sec);
|
int bgp_rte_mergable(rte *pri, rte *sec);
|
||||||
int bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best);
|
int bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best);
|
||||||
struct rte *bgp_rte_modify_stale(struct rte *r, struct linpool *pool);
|
struct rte *bgp_rte_modify_stale(struct rte *r, struct linpool *pool);
|
||||||
|
u32 bgp_rte_igp_metric(struct rte *);
|
||||||
void bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old);
|
void bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old);
|
||||||
int bgp_preexport(struct proto *, struct rte *);
|
int bgp_preexport(struct proto *, struct rte *);
|
||||||
int bgp_get_attr(const struct eattr *e, byte *buf, int buflen);
|
int bgp_get_attr(const struct eattr *e, byte *buf, int buflen);
|
||||||
|
|
|
@ -108,11 +108,9 @@
|
||||||
#include "ospf.h"
|
#include "ospf.h"
|
||||||
|
|
||||||
static int ospf_preexport(struct proto *P, rte *new);
|
static int ospf_preexport(struct proto *P, rte *new);
|
||||||
static void ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool);
|
|
||||||
static void ospf_store_tmp_attrs(struct rte *rt, struct linpool *pool);
|
|
||||||
static void ospf_reload_routes(struct channel *C);
|
static void ospf_reload_routes(struct channel *C);
|
||||||
static int ospf_rte_better(struct rte *new, struct rte *old);
|
static int ospf_rte_better(struct rte *new, struct rte *old);
|
||||||
static int ospf_rte_same(struct rte *new, struct rte *old);
|
static u32 ospf_rte_igp_metric(struct rte *rt);
|
||||||
static void ospf_disp(timer *timer);
|
static void ospf_disp(timer *timer);
|
||||||
|
|
||||||
|
|
||||||
|
@ -378,10 +376,8 @@ ospf_init(struct proto_config *CF)
|
||||||
P->reload_routes = ospf_reload_routes;
|
P->reload_routes = ospf_reload_routes;
|
||||||
P->feed_begin = ospf_feed_begin;
|
P->feed_begin = ospf_feed_begin;
|
||||||
P->feed_end = ospf_feed_end;
|
P->feed_end = ospf_feed_end;
|
||||||
P->make_tmp_attrs = ospf_make_tmp_attrs;
|
|
||||||
P->store_tmp_attrs = ospf_store_tmp_attrs;
|
|
||||||
P->rte_better = ospf_rte_better;
|
P->rte_better = ospf_rte_better;
|
||||||
P->rte_same = ospf_rte_same;
|
P->rte_igp_metric = ospf_rte_igp_metric;
|
||||||
|
|
||||||
return P;
|
return P;
|
||||||
}
|
}
|
||||||
|
@ -390,7 +386,9 @@ ospf_init(struct proto_config *CF)
|
||||||
static int
|
static int
|
||||||
ospf_rte_better(struct rte *new, struct rte *old)
|
ospf_rte_better(struct rte *new, struct rte *old)
|
||||||
{
|
{
|
||||||
if (new->u.ospf.metric1 == LSINFINITY)
|
u32 new_metric1 = ea_get_int(new->attrs->eattrs, EA_OSPF_METRIC1, LSINFINITY);
|
||||||
|
|
||||||
|
if (new_metric1 == LSINFINITY)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if(new->attrs->source < old->attrs->source) return 1;
|
if(new->attrs->source < old->attrs->source) return 1;
|
||||||
|
@ -398,27 +396,27 @@ ospf_rte_better(struct rte *new, struct rte *old)
|
||||||
|
|
||||||
if(new->attrs->source == RTS_OSPF_EXT2)
|
if(new->attrs->source == RTS_OSPF_EXT2)
|
||||||
{
|
{
|
||||||
if(new->u.ospf.metric2 < old->u.ospf.metric2) return 1;
|
u32 old_metric2 = ea_get_int(old->attrs->eattrs, EA_OSPF_METRIC2, LSINFINITY);
|
||||||
if(new->u.ospf.metric2 > old->u.ospf.metric2) return 0;
|
u32 new_metric2 = ea_get_int(new->attrs->eattrs, EA_OSPF_METRIC2, LSINFINITY);
|
||||||
|
if(new_metric2 < old_metric2) return 1;
|
||||||
|
if(new_metric2 > old_metric2) return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new->u.ospf.metric1 < old->u.ospf.metric1)
|
u32 old_metric1 = ea_get_int(old->attrs->eattrs, EA_OSPF_METRIC1, LSINFINITY);
|
||||||
|
if (new_metric1 < old_metric1)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0; /* Old is shorter or same */
|
return 0; /* Old is shorter or same */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static u32
|
||||||
ospf_rte_same(struct rte *new, struct rte *old)
|
ospf_rte_igp_metric(struct rte *rt)
|
||||||
{
|
{
|
||||||
/* new->attrs == old->attrs always */
|
if (rt->attrs->source == RTS_OSPF_EXT2)
|
||||||
return
|
return IGP_METRIC_UNKNOWN;
|
||||||
new->u.ospf.metric1 == old->u.ospf.metric1 &&
|
|
||||||
new->u.ospf.metric2 == old->u.ospf.metric2 &&
|
|
||||||
new->u.ospf.tag == old->u.ospf.tag &&
|
|
||||||
new->u.ospf.router_id == old->u.ospf.router_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return ea_get_int(rt->attrs->eattrs, EA_OSPF_METRIC1, LSINFINITY);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ospf_schedule_rtcalc(struct ospf_proto *p)
|
ospf_schedule_rtcalc(struct ospf_proto *p)
|
||||||
|
@ -500,26 +498,6 @@ ospf_preexport(struct proto *P, rte *e)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool)
|
|
||||||
{
|
|
||||||
rte_init_tmp_attrs(rt, pool, 4);
|
|
||||||
rte_make_tmp_attr(rt, EA_OSPF_METRIC1, EAF_TYPE_INT, rt->u.ospf.metric1);
|
|
||||||
rte_make_tmp_attr(rt, EA_OSPF_METRIC2, EAF_TYPE_INT, rt->u.ospf.metric2);
|
|
||||||
rte_make_tmp_attr(rt, EA_OSPF_TAG, EAF_TYPE_INT, rt->u.ospf.tag);
|
|
||||||
rte_make_tmp_attr(rt, EA_OSPF_ROUTER_ID, EAF_TYPE_ROUTER_ID, rt->u.ospf.router_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ospf_store_tmp_attrs(struct rte *rt, struct linpool *pool)
|
|
||||||
{
|
|
||||||
rte_init_tmp_attrs(rt, pool, 4);
|
|
||||||
rt->u.ospf.metric1 = rte_store_tmp_attr(rt, EA_OSPF_METRIC1);
|
|
||||||
rt->u.ospf.metric2 = rte_store_tmp_attr(rt, EA_OSPF_METRIC2);
|
|
||||||
rt->u.ospf.tag = rte_store_tmp_attr(rt, EA_OSPF_TAG);
|
|
||||||
rt->u.ospf.router_id = rte_store_tmp_attr(rt, EA_OSPF_ROUTER_ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ospf_shutdown - Finish of OSPF instance
|
* ospf_shutdown - Finish of OSPF instance
|
||||||
* @P: OSPF protocol instance
|
* @P: OSPF protocol instance
|
||||||
|
@ -609,16 +587,20 @@ ospf_get_route_info(rte * rte, byte * buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
buf += bsprintf(buf, " %s", type);
|
buf += bsprintf(buf, " %s", type);
|
||||||
buf += bsprintf(buf, " (%d/%d", rte->attrs->pref, rte->u.ospf.metric1);
|
buf += bsprintf(buf, " (%d/%d", rte->attrs->pref, ea_get_int(rte->attrs->eattrs, EA_OSPF_METRIC1, LSINFINITY));
|
||||||
if (rte->attrs->source == RTS_OSPF_EXT2)
|
if (rte->attrs->source == RTS_OSPF_EXT2)
|
||||||
buf += bsprintf(buf, "/%d", rte->u.ospf.metric2);
|
buf += bsprintf(buf, "/%d", ea_get_int(rte->attrs->eattrs, EA_OSPF_METRIC2, LSINFINITY));
|
||||||
buf += bsprintf(buf, ")");
|
buf += bsprintf(buf, ")");
|
||||||
if ((rte->attrs->source == RTS_OSPF_EXT1 || rte->attrs->source == RTS_OSPF_EXT2) && rte->u.ospf.tag)
|
if (rte->attrs->source == RTS_OSPF_EXT1 || rte->attrs->source == RTS_OSPF_EXT2)
|
||||||
{
|
{
|
||||||
buf += bsprintf(buf, " [%x]", rte->u.ospf.tag);
|
eattr *ea = ea_find(rte->attrs->eattrs, EA_OSPF_TAG);
|
||||||
|
if (ea && (ea->u.data > 0))
|
||||||
|
buf += bsprintf(buf, " [%x]", ea->u.data);
|
||||||
}
|
}
|
||||||
if (rte->u.ospf.router_id)
|
|
||||||
buf += bsprintf(buf, " [%R]", rte->u.ospf.router_id);
|
eattr *ea = ea_find(rte->attrs->eattrs, EA_OSPF_ROUTER_ID);
|
||||||
|
if (ea)
|
||||||
|
buf += bsprintf(buf, " [%R]", ea->u.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
|
@ -144,7 +144,7 @@ orta_compare(const struct ospf_proto *p, const orta *new, const orta *old)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (old->type == RTS_DUMMY)
|
if (!old->type)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* Prefer intra-area to inter-area to externals */
|
/* Prefer intra-area to inter-area to externals */
|
||||||
|
@ -195,7 +195,7 @@ orta_compare_asbr(const struct ospf_proto *p, const orta *new, const orta *old)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (old->type == RTS_DUMMY)
|
if (!old->type)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!p->rfc1583)
|
if (!p->rfc1583)
|
||||||
|
@ -225,7 +225,7 @@ orta_compare_ext(const struct ospf_proto *p, const orta *new, const orta *old)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (old->type == RTS_DUMMY)
|
if (!old->type)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* 16.4 (6a) - prefer routes with lower type */
|
/* 16.4 (6a) - prefer routes with lower type */
|
||||||
|
@ -2062,23 +2062,45 @@ again1:
|
||||||
|
|
||||||
if (reload || ort_changed(nf, &a0))
|
if (reload || ort_changed(nf, &a0))
|
||||||
{
|
{
|
||||||
|
a0.eattrs = alloca(sizeof(ea_list) + 4 * sizeof(eattr));
|
||||||
|
memset(a0.eattrs, 0, sizeof(ea_list));
|
||||||
|
|
||||||
|
nf->old_metric1 = nf->n.metric1;
|
||||||
|
nf->old_metric2 = nf->n.metric2;
|
||||||
|
nf->old_tag = nf->n.tag;
|
||||||
|
nf->old_rid = nf->n.rid;
|
||||||
|
|
||||||
|
a0.eattrs->attrs[a0.eattrs->count++] = (eattr) {
|
||||||
|
.id = EA_OSPF_METRIC1,
|
||||||
|
.type = EAF_TYPE_INT,
|
||||||
|
.u.data = nf->n.metric1,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (nf->n.type == RTS_OSPF_EXT2)
|
||||||
|
a0.eattrs->attrs[a0.eattrs->count++] = (eattr) {
|
||||||
|
.id = EA_OSPF_METRIC2,
|
||||||
|
.type = EAF_TYPE_INT,
|
||||||
|
.u.data = nf->n.metric2,
|
||||||
|
};
|
||||||
|
|
||||||
|
if ((nf->n.type == RTS_OSPF_EXT1) || (nf->n.type == RTS_OSPF_EXT2))
|
||||||
|
a0.eattrs->attrs[a0.eattrs->count++] = (eattr) {
|
||||||
|
.id = EA_OSPF_TAG,
|
||||||
|
.type = EAF_TYPE_INT,
|
||||||
|
.u.data = nf->n.tag,
|
||||||
|
};
|
||||||
|
|
||||||
|
a0.eattrs->attrs[a0.eattrs->count++] = (eattr) {
|
||||||
|
.id = EA_OSPF_ROUTER_ID,
|
||||||
|
.type = EAF_TYPE_ROUTER_ID,
|
||||||
|
.u.data = nf->n.rid,
|
||||||
|
};
|
||||||
|
|
||||||
rta *a = rta_lookup(&a0);
|
rta *a = rta_lookup(&a0);
|
||||||
rte *e = rte_get_temp(a, p->p.main_source);
|
rte *e = rte_get_temp(a, p->p.main_source);
|
||||||
|
|
||||||
rta_free(nf->old_rta);
|
rta_free(nf->old_rta);
|
||||||
nf->old_rta = rta_clone(a);
|
nf->old_rta = rta_clone(a);
|
||||||
e->u.ospf.metric1 = nf->old_metric1 = nf->n.metric1;
|
|
||||||
e->u.ospf.metric2 = nf->old_metric2 = nf->n.metric2;
|
|
||||||
e->u.ospf.tag = nf->old_tag = nf->n.tag;
|
|
||||||
e->u.ospf.router_id = nf->old_rid = nf->n.rid;
|
|
||||||
e->pflags = EA_ID_FLAG(EA_OSPF_METRIC1) | EA_ID_FLAG(EA_OSPF_ROUTER_ID);
|
|
||||||
|
|
||||||
if (nf->n.type == RTS_OSPF_EXT2)
|
|
||||||
e->pflags |= EA_ID_FLAG(EA_OSPF_METRIC2);
|
|
||||||
|
|
||||||
/* Perhaps onfly if tag is non-zero? */
|
|
||||||
if ((nf->n.type == RTS_OSPF_EXT1) || (nf->n.type == RTS_OSPF_EXT2))
|
|
||||||
e->pflags |= EA_ID_FLAG(EA_OSPF_TAG);
|
|
||||||
|
|
||||||
DBG("Mod rte type %d - %N via %I on iface %s, met %d\n",
|
DBG("Mod rte type %d - %N via %I on iface %s, met %d\n",
|
||||||
a0.source, nf->fn.addr, a0.gw, a0.iface ? a0.iface->name : "(none)", nf->n.metric1);
|
a0.source, nf->fn.addr, a0.gw, a0.iface ? a0.iface->name : "(none)", nf->n.metric1);
|
||||||
|
|
|
@ -188,12 +188,28 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
|
||||||
a0.nh.iface = rt->from->ifa->iface;
|
a0.nh.iface = rt->from->ifa->iface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a0.eattrs = alloca(sizeof(ea_list) + 3*sizeof(eattr));
|
||||||
|
memset(a0.eattrs, 0, sizeof(ea_list)); /* Zero-ing only the ea_list header */
|
||||||
|
a0.eattrs->count = 3;
|
||||||
|
a0.eattrs->attrs[0] = (eattr) {
|
||||||
|
.id = EA_RIP_METRIC,
|
||||||
|
.type = EAF_TYPE_INT,
|
||||||
|
.u.data = rt_metric,
|
||||||
|
};
|
||||||
|
a0.eattrs->attrs[1] = (eattr) {
|
||||||
|
.id = EA_RIP_TAG,
|
||||||
|
.type = EAF_TYPE_INT,
|
||||||
|
.u.data = rt_tag,
|
||||||
|
};
|
||||||
|
a0.eattrs->attrs[2] = (eattr) {
|
||||||
|
.id = EA_RIP_FROM,
|
||||||
|
.type = EAF_TYPE_PTR,
|
||||||
|
.u.data = (uintptr_t) a0.nh.iface,
|
||||||
|
};
|
||||||
|
|
||||||
rta *a = rta_lookup(&a0);
|
rta *a = rta_lookup(&a0);
|
||||||
rte *e = rte_get_temp(a, p->p.main_source);
|
rte *e = rte_get_temp(a, p->p.main_source);
|
||||||
|
|
||||||
e->u.rip.from = a0.nh.iface;
|
|
||||||
e->u.rip.metric = rt_metric;
|
|
||||||
e->u.rip.tag = rt_tag;
|
|
||||||
e->pflags = EA_ID_FLAG(EA_RIP_METRIC) | EA_ID_FLAG(EA_RIP_TAG);
|
e->pflags = EA_ID_FLAG(EA_RIP_METRIC) | EA_ID_FLAG(EA_RIP_TAG);
|
||||||
|
|
||||||
rte_update(&p->p, en->n.addr, e);
|
rte_update(&p->p, en->n.addr, e);
|
||||||
|
@ -307,8 +323,9 @@ rip_rt_notify(struct proto *P, struct channel *ch UNUSED, struct network *net, s
|
||||||
if (new)
|
if (new)
|
||||||
{
|
{
|
||||||
/* Update */
|
/* Update */
|
||||||
u32 rt_metric = ea_get_int(new->attrs->eattrs, EA_RIP_METRIC, 1);
|
|
||||||
u32 rt_tag = ea_get_int(new->attrs->eattrs, EA_RIP_TAG, 0);
|
u32 rt_tag = ea_get_int(new->attrs->eattrs, EA_RIP_TAG, 0);
|
||||||
|
u32 rt_metric = ea_get_int(new->attrs->eattrs, EA_RIP_METRIC, 1);
|
||||||
|
struct iface *rt_from = (struct iface *) ea_get_int(new->attrs->eattrs, EA_RIP_FROM, 0);
|
||||||
|
|
||||||
if (rt_metric > p->infinity)
|
if (rt_metric > p->infinity)
|
||||||
{
|
{
|
||||||
|
@ -339,7 +356,7 @@ rip_rt_notify(struct proto *P, struct channel *ch UNUSED, struct network *net, s
|
||||||
en->valid = RIP_ENTRY_VALID;
|
en->valid = RIP_ENTRY_VALID;
|
||||||
en->metric = rt_metric;
|
en->metric = rt_metric;
|
||||||
en->tag = rt_tag;
|
en->tag = rt_tag;
|
||||||
en->from = (new->src->proto == P) ? new->u.rip.from : NULL;
|
en->from = (new->src->proto == P) ? rt_from : NULL;
|
||||||
en->iface = new->attrs->nh.iface;
|
en->iface = new->attrs->nh.iface;
|
||||||
en->next_hop = new->attrs->nh.gw;
|
en->next_hop = new->attrs->nh.gw;
|
||||||
}
|
}
|
||||||
|
@ -1068,37 +1085,24 @@ rip_reload_routes(struct channel *C)
|
||||||
rip_kick_timer(p);
|
rip_kick_timer(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
rip_make_tmp_attrs(struct rte *rt, struct linpool *pool)
|
|
||||||
{
|
|
||||||
rte_init_tmp_attrs(rt, pool, 2);
|
|
||||||
rte_make_tmp_attr(rt, EA_RIP_METRIC, EAF_TYPE_INT, rt->u.rip.metric);
|
|
||||||
rte_make_tmp_attr(rt, EA_RIP_TAG, EAF_TYPE_INT, rt->u.rip.tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
rip_store_tmp_attrs(struct rte *rt, struct linpool *pool)
|
|
||||||
{
|
|
||||||
rte_init_tmp_attrs(rt, pool, 2);
|
|
||||||
rt->u.rip.metric = rte_store_tmp_attr(rt, EA_RIP_METRIC);
|
|
||||||
rt->u.rip.tag = rte_store_tmp_attr(rt, EA_RIP_TAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
rip_rte_better(struct rte *new, struct rte *old)
|
rip_rte_better(struct rte *new, struct rte *old)
|
||||||
{
|
{
|
||||||
return new->u.rip.metric < old->u.rip.metric;
|
ASSERT_DIE(new->src == old->src);
|
||||||
|
struct rip_proto *p = (struct rip_proto *) new->src->proto;
|
||||||
|
|
||||||
|
u32 new_metric = ea_get_int(new->attrs->eattrs, EA_RIP_METRIC, p->infinity);
|
||||||
|
u32 old_metric = ea_get_int(old->attrs->eattrs, EA_RIP_METRIC, p->infinity);
|
||||||
|
|
||||||
|
return new_metric < old_metric;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static u32
|
||||||
rip_rte_same(struct rte *new, struct rte *old)
|
rip_rte_igp_metric(struct rte *rt)
|
||||||
{
|
{
|
||||||
return ((new->u.rip.metric == old->u.rip.metric) &&
|
return ea_get_int(rt->attrs->eattrs, EA_RIP_METRIC, IGP_METRIC_UNKNOWN);
|
||||||
(new->u.rip.tag == old->u.rip.tag) &&
|
|
||||||
(new->u.rip.from == old->u.rip.from));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rip_postconfig(struct proto_config *CF)
|
rip_postconfig(struct proto_config *CF)
|
||||||
{
|
{
|
||||||
|
@ -1120,10 +1124,8 @@ rip_init(struct proto_config *CF)
|
||||||
P->rt_notify = rip_rt_notify;
|
P->rt_notify = rip_rt_notify;
|
||||||
P->neigh_notify = rip_neigh_notify;
|
P->neigh_notify = rip_neigh_notify;
|
||||||
P->reload_routes = rip_reload_routes;
|
P->reload_routes = rip_reload_routes;
|
||||||
P->make_tmp_attrs = rip_make_tmp_attrs;
|
|
||||||
P->store_tmp_attrs = rip_store_tmp_attrs;
|
|
||||||
P->rte_better = rip_rte_better;
|
P->rte_better = rip_rte_better;
|
||||||
P->rte_same = rip_rte_same;
|
P->rte_igp_metric = rip_rte_igp_metric;
|
||||||
|
|
||||||
return P;
|
return P;
|
||||||
}
|
}
|
||||||
|
@ -1198,10 +1200,14 @@ rip_reconfigure(struct proto *P, struct proto_config *CF)
|
||||||
static void
|
static void
|
||||||
rip_get_route_info(rte *rte, byte *buf)
|
rip_get_route_info(rte *rte, byte *buf)
|
||||||
{
|
{
|
||||||
buf += bsprintf(buf, " (%d/%d)", rte->attrs->pref, rte->u.rip.metric);
|
struct rip_proto *p = (struct rip_proto *) rte->src->proto;
|
||||||
|
u32 rt_metric = ea_get_int(rte->attrs->eattrs, EA_RIP_METRIC, p->infinity);
|
||||||
|
u32 rt_tag = ea_get_int(rte->attrs->eattrs, EA_RIP_TAG, 0);
|
||||||
|
|
||||||
if (rte->u.rip.tag)
|
buf += bsprintf(buf, " (%d/%d)", rte->attrs->pref, rt_metric);
|
||||||
bsprintf(buf, " [%04x]", rte->u.rip.tag);
|
|
||||||
|
if (rt_tag)
|
||||||
|
bsprintf(buf, " [%04x]", rt_tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
|
@ -197,6 +197,7 @@ struct rip_rte
|
||||||
|
|
||||||
#define EA_RIP_METRIC EA_CODE(PROTOCOL_RIP, 0)
|
#define EA_RIP_METRIC EA_CODE(PROTOCOL_RIP, 0)
|
||||||
#define EA_RIP_TAG EA_CODE(PROTOCOL_RIP, 1)
|
#define EA_RIP_TAG EA_CODE(PROTOCOL_RIP, 1)
|
||||||
|
#define EA_RIP_FROM EA_CODE(PROTOCOL_RIP, 2)
|
||||||
|
|
||||||
static inline int rip_is_v2(struct rip_proto *p)
|
static inline int rip_is_v2(struct rip_proto *p)
|
||||||
{ return p->rip2; }
|
{ return p->rip2; }
|
||||||
|
|
|
@ -582,16 +582,21 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
|
||||||
done:
|
done:
|
||||||
e = rte_get_temp(&a);
|
e = rte_get_temp(&a);
|
||||||
e->net = net;
|
e->net = net;
|
||||||
e->u.krt.src = src;
|
|
||||||
e->u.krt.proto = src2;
|
ea_list *ea = alloca(sizeof(ea_list) + 1 * sizeof(eattr));
|
||||||
e->u.krt.seen = 0;
|
*ea = (ea_list) { .count = 1, .next = e->attrs->eattrs };
|
||||||
e->u.krt.best = 0;
|
e->attrs->eattrs = ea;
|
||||||
e->u.krt.metric = 0;
|
|
||||||
|
ea->attrs[0] = (eattr) {
|
||||||
|
.id = EA_KRT_SOURCE,
|
||||||
|
.type = EAF_TYPE_INT,
|
||||||
|
.u.data = src2,
|
||||||
|
};
|
||||||
|
|
||||||
if (scan)
|
if (scan)
|
||||||
krt_got_route(p, e);
|
krt_got_route(p, e, src);
|
||||||
else
|
else
|
||||||
krt_got_route_async(p, e, new);
|
krt_got_route_async(p, e, new, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -1397,8 +1397,6 @@ nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh)
|
||||||
|
|
||||||
if (p->af == AF_MPLS)
|
if (p->af == AF_MPLS)
|
||||||
priority = 0;
|
priority = 0;
|
||||||
else if (a->source == RTS_DUMMY)
|
|
||||||
priority = e->u.krt.metric;
|
|
||||||
else if (KRT_CF->sys.metric)
|
else if (KRT_CF->sys.metric)
|
||||||
priority = KRT_CF->sys.metric;
|
priority = KRT_CF->sys.metric;
|
||||||
else if ((op != NL_OP_DELETE) && (ea = ea_find(eattrs, EA_KRT_METRIC)))
|
else if ((op != NL_OP_DELETE) && (ea = ea_find(eattrs, EA_KRT_METRIC)))
|
||||||
|
@ -1582,16 +1580,26 @@ nl_announce_route(struct nl_parse_state *s)
|
||||||
{
|
{
|
||||||
rte *e = rte_get_temp(s->attrs, s->proto->p.main_source);
|
rte *e = rte_get_temp(s->attrs, s->proto->p.main_source);
|
||||||
e->net = s->net;
|
e->net = s->net;
|
||||||
e->u.krt.src = s->krt_src;
|
|
||||||
e->u.krt.proto = s->krt_proto;
|
ea_list *ea = alloca(sizeof(ea_list) + 2 * sizeof(eattr));
|
||||||
e->u.krt.seen = 0;
|
*ea = (ea_list) { .count = 2, .next = e->attrs->eattrs };
|
||||||
e->u.krt.best = 0;
|
e->attrs->eattrs = ea;
|
||||||
e->u.krt.metric = s->krt_metric;
|
|
||||||
|
ea->attrs[0] = (eattr) {
|
||||||
|
.id = EA_KRT_SOURCE,
|
||||||
|
.type = EAF_TYPE_INT,
|
||||||
|
.u.data = s->krt_proto,
|
||||||
|
};
|
||||||
|
ea->attrs[1] = (eattr) {
|
||||||
|
.id = EA_KRT_METRIC,
|
||||||
|
.type = EAF_TYPE_INT,
|
||||||
|
.u.data = s->krt_metric,
|
||||||
|
};
|
||||||
|
|
||||||
if (s->scan)
|
if (s->scan)
|
||||||
krt_got_route(s->proto, e);
|
krt_got_route(s->proto, e, s->krt_src);
|
||||||
else
|
else
|
||||||
krt_got_route_async(s->proto, e, s->new);
|
krt_got_route_async(s->proto, e, s->new, s->krt_src);
|
||||||
|
|
||||||
s->net = NULL;
|
s->net = NULL;
|
||||||
s->attrs = NULL;
|
s->attrs = NULL;
|
||||||
|
|
|
@ -277,22 +277,23 @@ static struct tbf rl_alien = TBF_DEFAULT_LOG_LIMITS;
|
||||||
* the same key.
|
* the same key.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static inline u32
|
||||||
|
krt_metric(rte *a)
|
||||||
|
{
|
||||||
|
eattr *ea = ea_find(a->attrs->eattrs, EA_KRT_METRIC);
|
||||||
|
return ea ? ea->u.data : 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
krt_same_key(rte *a, rte *b)
|
krt_same_key(rte *a, rte *b)
|
||||||
{
|
{
|
||||||
return a->u.krt.metric == b->u.krt.metric;
|
return (krt_metric(a) == krt_metric(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
krt_uptodate(rte *a, rte *b)
|
krt_uptodate(rte *a, rte *b)
|
||||||
{
|
{
|
||||||
if (a->attrs != b->attrs)
|
return (a->attrs == b->attrs);
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (a->u.krt.proto != b->u.krt.proto)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -301,8 +302,6 @@ krt_learn_announce_update(struct krt_proto *p, rte *e)
|
||||||
net *n = e->net;
|
net *n = e->net;
|
||||||
rta *aa = rta_clone(e->attrs);
|
rta *aa = rta_clone(e->attrs);
|
||||||
rte *ee = rte_get_temp(aa, p->p.main_source);
|
rte *ee = rte_get_temp(aa, p->p.main_source);
|
||||||
ee->pflags = EA_ID_FLAG(EA_KRT_SOURCE) | EA_ID_FLAG(EA_KRT_METRIC);
|
|
||||||
ee->u.krt = e->u.krt;
|
|
||||||
rte_update(&p->p, n->n.addr, ee);
|
rte_update(&p->p, n->n.addr, ee);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,7 +330,7 @@ krt_learn_scan(struct krt_proto *p, rte *e)
|
||||||
{
|
{
|
||||||
krt_trace_in_rl(&rl_alien, p, e, "[alien] seen");
|
krt_trace_in_rl(&rl_alien, p, e, "[alien] seen");
|
||||||
rte_free(e);
|
rte_free(e);
|
||||||
m->u.krt.seen = 1;
|
m->pflags |= KRT_REF_SEEN;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -347,7 +346,7 @@ krt_learn_scan(struct krt_proto *p, rte *e)
|
||||||
{
|
{
|
||||||
e->next = n->routes;
|
e->next = n->routes;
|
||||||
n->routes = e;
|
n->routes = e;
|
||||||
e->u.krt.seen = 1;
|
e->pflags |= KRT_REF_SEEN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,24 +376,23 @@ again:
|
||||||
ee = &n->routes;
|
ee = &n->routes;
|
||||||
while (e = *ee)
|
while (e = *ee)
|
||||||
{
|
{
|
||||||
if (e->u.krt.best)
|
if (e->pflags & KRT_REF_BEST)
|
||||||
old_best = e;
|
old_best = e;
|
||||||
|
|
||||||
if (!e->u.krt.seen)
|
if (!(e->pflags & KRT_REF_SEEN))
|
||||||
{
|
{
|
||||||
*ee = e->next;
|
*ee = e->next;
|
||||||
rte_free(e);
|
rte_free(e);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!best || best->u.krt.metric > e->u.krt.metric)
|
if (!best || krt_metric(best) > krt_metric(e))
|
||||||
{
|
{
|
||||||
best = e;
|
best = e;
|
||||||
pbest = ee;
|
pbest = ee;
|
||||||
}
|
}
|
||||||
|
|
||||||
e->u.krt.seen = 0;
|
e->pflags &= ~(KRT_REF_SEEN | KRT_REF_BEST);
|
||||||
e->u.krt.best = 0;
|
|
||||||
ee = &e->next;
|
ee = &e->next;
|
||||||
}
|
}
|
||||||
if (!n->routes)
|
if (!n->routes)
|
||||||
|
@ -408,18 +406,18 @@ again:
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
|
|
||||||
best->u.krt.best = 1;
|
best->pflags |= KRT_REF_BEST;
|
||||||
*pbest = best->next;
|
*pbest = best->next;
|
||||||
best->next = n->routes;
|
best->next = n->routes;
|
||||||
n->routes = best;
|
n->routes = best;
|
||||||
|
|
||||||
if ((best != old_best) || p->reload)
|
if ((best != old_best) || p->reload)
|
||||||
{
|
{
|
||||||
DBG("%I/%d: announcing (metric=%d)\n", n->n.prefix, n->n.pxlen, best->u.krt.metric);
|
DBG("%I/%d: announcing (metric=%d)\n", n->n.prefix, n->n.pxlen, krt_metric(best));
|
||||||
krt_learn_announce_update(p, best);
|
krt_learn_announce_update(p, best);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
DBG("%I/%d: uptodate (metric=%d)\n", n->n.prefix, n->n.pxlen, best->u.krt.metric);
|
DBG("%I/%d: uptodate (metric=%d)\n", n->n.prefix, n->n.pxlen, krt_metric(best));
|
||||||
}
|
}
|
||||||
FIB_ITERATE_END;
|
FIB_ITERATE_END;
|
||||||
|
|
||||||
|
@ -479,18 +477,18 @@ krt_learn_async(struct krt_proto *p, rte *e, int new)
|
||||||
bestp = &n->routes;
|
bestp = &n->routes;
|
||||||
for(gg=&n->routes; g=*gg; gg=&g->next)
|
for(gg=&n->routes; g=*gg; gg=&g->next)
|
||||||
{
|
{
|
||||||
if (best->u.krt.metric > g->u.krt.metric)
|
if (krt_metric(best) > krt_metric(g))
|
||||||
{
|
{
|
||||||
best = g;
|
best = g;
|
||||||
bestp = gg;
|
bestp = gg;
|
||||||
}
|
}
|
||||||
|
|
||||||
g->u.krt.best = 0;
|
g->pflags &= ~KRT_REF_BEST;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (best)
|
if (best)
|
||||||
{
|
{
|
||||||
best->u.krt.best = 1;
|
best->pflags |= KRT_REF_BEST;
|
||||||
*bestp = best->next;
|
*bestp = best->next;
|
||||||
best->next = n->routes;
|
best->next = n->routes;
|
||||||
n->routes = best;
|
n->routes = best;
|
||||||
|
@ -531,12 +529,6 @@ krt_dump(struct proto *P)
|
||||||
rt_dump(p->krt_table);
|
rt_dump(p->krt_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
krt_dump_attrs(rte *e)
|
|
||||||
{
|
|
||||||
debug(" [m=%d,p=%d]", e->u.krt.metric, e->u.krt.proto);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -627,13 +619,14 @@ krt_same_dest(rte *k, rte *e)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_got_route(struct krt_proto *p, rte *e)
|
krt_got_route(struct krt_proto *p, rte *e, s8 src)
|
||||||
{
|
{
|
||||||
rte *new = NULL, *rt_free = NULL;
|
rte *new = NULL, *rt_free = NULL;
|
||||||
net *n = e->net;
|
net *n = e->net;
|
||||||
|
e->pflags = 0;
|
||||||
|
|
||||||
#ifdef KRT_ALLOW_LEARN
|
#ifdef KRT_ALLOW_LEARN
|
||||||
switch (e->u.krt.src)
|
switch (src)
|
||||||
{
|
{
|
||||||
case KRT_SRC_KERNEL:
|
case KRT_SRC_KERNEL:
|
||||||
goto ignore;
|
goto ignore;
|
||||||
|
@ -755,11 +748,12 @@ krt_prune(struct krt_proto *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_got_route_async(struct krt_proto *p, rte *e, int new)
|
krt_got_route_async(struct krt_proto *p, rte *e, int new, s8 src)
|
||||||
{
|
{
|
||||||
net *net = e->net;
|
net *net = e->net;
|
||||||
|
e->pflags = 0;
|
||||||
|
|
||||||
switch (e->u.krt.src)
|
switch (src)
|
||||||
{
|
{
|
||||||
case KRT_SRC_BIRD:
|
case KRT_SRC_BIRD:
|
||||||
/* Should be filtered by the back end */
|
/* Should be filtered by the back end */
|
||||||
|
@ -889,22 +883,6 @@ krt_scan_timer_kick(struct krt_proto *p)
|
||||||
* Updates
|
* Updates
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
|
||||||
krt_make_tmp_attrs(struct rte *rt, struct linpool *pool)
|
|
||||||
{
|
|
||||||
rte_init_tmp_attrs(rt, pool, 2);
|
|
||||||
rte_make_tmp_attr(rt, EA_KRT_SOURCE, EAF_TYPE_INT, rt->u.krt.proto);
|
|
||||||
rte_make_tmp_attr(rt, EA_KRT_METRIC, EAF_TYPE_INT, rt->u.krt.metric);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
krt_store_tmp_attrs(struct rte *rt, struct linpool *pool)
|
|
||||||
{
|
|
||||||
rte_init_tmp_attrs(rt, pool, 2);
|
|
||||||
rt->u.krt.proto = rte_store_tmp_attr(rt, EA_KRT_SOURCE);
|
|
||||||
rt->u.krt.metric = rte_store_tmp_attr(rt, EA_KRT_METRIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
krt_preexport(struct proto *P, rte *e)
|
krt_preexport(struct proto *P, rte *e)
|
||||||
{
|
{
|
||||||
|
@ -984,14 +962,6 @@ krt_feed_end(struct channel *C)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
krt_rte_same(rte *a, rte *b)
|
|
||||||
{
|
|
||||||
/* src is always KRT_SRC_ALIEN and type is irrelevant */
|
|
||||||
return (a->u.krt.proto == b->u.krt.proto) && (a->u.krt.metric == b->u.krt.metric);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Protocol glue
|
* Protocol glue
|
||||||
*/
|
*/
|
||||||
|
@ -1050,9 +1020,6 @@ krt_init(struct proto_config *CF)
|
||||||
p->p.if_notify = krt_if_notify;
|
p->p.if_notify = krt_if_notify;
|
||||||
p->p.reload_routes = krt_reload_routes;
|
p->p.reload_routes = krt_reload_routes;
|
||||||
p->p.feed_end = krt_feed_end;
|
p->p.feed_end = krt_feed_end;
|
||||||
p->p.make_tmp_attrs = krt_make_tmp_attrs;
|
|
||||||
p->p.store_tmp_attrs = krt_store_tmp_attrs;
|
|
||||||
p->p.rte_same = krt_rte_same;
|
|
||||||
|
|
||||||
krt_sys_init(p);
|
krt_sys_init(p);
|
||||||
return &p->p;
|
return &p->p;
|
||||||
|
@ -1210,6 +1177,5 @@ struct protocol proto_unix_kernel = {
|
||||||
.get_attr = krt_get_attr,
|
.get_attr = krt_get_attr,
|
||||||
#ifdef KRT_ALLOW_LEARN
|
#ifdef KRT_ALLOW_LEARN
|
||||||
.dump = krt_dump,
|
.dump = krt_dump,
|
||||||
.dump_attrs = krt_dump_attrs,
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,6 +24,9 @@ struct kif_proto;
|
||||||
#define EA_KRT_SOURCE EA_CODE(PROTOCOL_KERNEL, 0)
|
#define EA_KRT_SOURCE EA_CODE(PROTOCOL_KERNEL, 0)
|
||||||
#define EA_KRT_METRIC EA_CODE(PROTOCOL_KERNEL, 1)
|
#define EA_KRT_METRIC EA_CODE(PROTOCOL_KERNEL, 1)
|
||||||
|
|
||||||
|
#define KRT_REF_SEEN 0x1 /* Seen in table */
|
||||||
|
#define KRT_REF_BEST 0x2 /* Best in table */
|
||||||
|
|
||||||
/* Whenever we recognize our own routes, we allow learing of foreign routes */
|
/* Whenever we recognize our own routes, we allow learing of foreign routes */
|
||||||
|
|
||||||
#ifdef CONFIG_SELF_CONSCIOUS
|
#ifdef CONFIG_SELF_CONSCIOUS
|
||||||
|
@ -76,8 +79,8 @@ extern pool *krt_pool;
|
||||||
|
|
||||||
struct proto_config * kif_init_config(int class);
|
struct proto_config * kif_init_config(int class);
|
||||||
void kif_request_scan(void);
|
void kif_request_scan(void);
|
||||||
void krt_got_route(struct krt_proto *p, struct rte *e);
|
void krt_got_route(struct krt_proto *p, struct rte *e, s8 src);
|
||||||
void krt_got_route_async(struct krt_proto *p, struct rte *e, int new);
|
void krt_got_route_async(struct krt_proto *p, struct rte *e, int new, s8 src);
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
krt_get_sync_error(struct krt_proto *p, struct rte *e)
|
krt_get_sync_error(struct krt_proto *p, struct rte *e)
|
||||||
|
|
Loading…
Reference in a new issue