1
0
mirror of https://gitlab.labs.nic.cz/labs/bird.git synced 2024-05-11 16:54:54 +00:00

Initial commit on integrated BIRD

New data types net_addr and variants (in lib/net.h) describing
network addresses (prefix/pxlen). Modifications of FIB structures
to handle these data types and changing everything to use these
data types instead of prefix/pxlen pairs where possible.

The commit is WiP, some protocols are not yet updated (BGP, Kernel),
and the code contains some temporary scaffolding.

Comments are welcome.
This commit is contained in:
Ondrej Zajicek (work)
2015-11-05 12:48:52 +01:00
parent 8eb8e546dc
commit fe9f1a6ded
42 changed files with 875 additions and 500 deletions

View File

@@ -78,8 +78,7 @@ struct rip_auth_tail
/* Internal representation of RTE block data */
struct rip_block
{
ip_addr prefix;
int pxlen;
net_addr net;
u32 metric;
u16 tag;
u16 no_af;
@@ -115,17 +114,17 @@ rip_put_block(struct rip_proto *p, byte *pos, struct rip_block *rte)
struct rip_block_v2 *block = (void *) pos;
block->family = rte->no_af ? 0 : htons(RIP_AF_IPV4);
block->tag = htons(rte->tag);
block->network = ip4_hton(ipa_to_ip4(rte->prefix));
block->netmask = ip4_hton(ip4_mkmask(rte->pxlen));
block->network = ip4_hton(net4_prefix(&rte->net));
block->netmask = ip4_hton(ip4_mkmask(net4_pxlen(&rte->net)));
block->next_hop = ip4_hton(ipa_to_ip4(rte->next_hop));
block->metric = htonl(rte->metric);
}
else /* RIPng */
{
struct rip_block_ng *block = (void *) pos;
block->prefix = ip6_hton(ipa_to_ip6(rte->prefix));
block->prefix = ip6_hton(net6_prefix(&rte->net));
block->tag = htons(rte->tag);
block->pxlen = rte->pxlen;
block->pxlen = net6_pxlen(&rte->net);
block->metric = rte->metric;
}
}
@@ -151,8 +150,8 @@ rip_get_block(struct rip_proto *p, byte *pos, struct rip_block *rte)
if (block->family != (rte->no_af ? 0 : htons(RIP_AF_IPV4)))
return 0;
rte->prefix = ipa_from_ip4(ip4_ntoh(block->network));
rte->pxlen = ip4_masklen(ip4_ntoh(block->netmask));
uint pxlen = ip4_masklen(ip4_ntoh(block->netmask));
net_fill_ip4(&rte->net, ip4_ntoh(block->network), pxlen);
rte->metric = ntohl(block->metric);
rte->tag = ntohs(block->tag);
rte->next_hop = ipa_from_ip4(ip4_ntoh(block->next_hop));
@@ -171,8 +170,8 @@ rip_get_block(struct rip_proto *p, byte *pos, struct rip_block *rte)
return 0;
}
rte->prefix = ipa_from_ip6(ip6_ntoh(block->prefix));
rte->pxlen = block->pxlen;
uint pxlen = (block->pxlen < IP6_MAX_PREFIX_LENGTH) ? block->pxlen : 255;
net_fill_ip6(&rte->net, ip6_ntoh(block->prefix), pxlen);
rte->metric = block->metric;
rte->tag = ntohs(block->tag);
/* rte->next_hop is deliberately kept unmodified */;
@@ -385,8 +384,9 @@ rip_receive_request(struct rip_proto *p, struct rip_iface *ifa, struct rip_packe
if (!rip_get_block(p, pos, &b))
return;
/* Special case - zero prefix, infinity metric */
if (ipa_nonzero(b.prefix) || b.pxlen || (b.metric != p->infinity))
/* Special case - infinity metric, for RIPng also zero prefix */
if ((b.metric != p->infinity) ||
(rip_is_ng(p) && !net_zero_ip6((net_addr_ip6 *) &b.net)))
return;
/* We do nothing if TX is already active */
@@ -444,23 +444,23 @@ rip_send_response(struct rip_proto *p, struct rip_iface *ifa)
}
struct rip_block rte = {
.prefix = en->n.prefix,
.pxlen = en->n.pxlen,
.metric = en->metric,
.tag = en->tag
};
net_copy(&rte.net, en->n.addr);
if (en->iface == ifa->iface)
rte.next_hop = en->next_hop;
if (rip_is_v2(p) && (ifa->cf->version == RIP_V1))
{
/* Skipping subnets (i.e. not hosts, classful networks or default route) */
if (ip4_masklen(ip4_class_mask(ipa_to_ip4(en->n.prefix))) != en->n.pxlen)
if (ip4_masklen(ip4_class_mask(net4_prefix(&rte.net))) != rte.net.pxlen)
goto next_entry;
rte.tag = 0;
rte.pxlen = 0;
rte.net.pxlen = 0;
rte.next_hop = IPA_NONE;
}
@@ -476,7 +476,7 @@ rip_send_response(struct rip_proto *p, struct rip_iface *ifa)
goto next_entry;
}
// TRACE(D_PACKETS, " %I/%d -> %I metric %d", rte.prefix, rte.pxlen, rte.next_hop, rte.metric);
// TRACE(D_PACKETS, " %N -> %I metric %d", &rte.net, rte.next_hop, rte.metric);
/* RIPng next hop entry */
if (rip_is_ng(p) && !ipa_equal(rte.next_hop, last_next_hop))
@@ -577,23 +577,25 @@ rip_receive_response(struct rip_proto *p, struct rip_iface *ifa, struct rip_pack
if (!rip_get_block(p, pos, &rte))
continue;
int c = ipa_classify_net(rte.prefix);
if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
SKIP("invalid prefix");
if (rip_is_v2(p) && (pkt->version == RIP_V1))
{
if (ifa->cf->check_zero && (rte.tag || rte.pxlen || ipa_nonzero(rte.next_hop)))
if (ifa->cf->check_zero && (rte.tag || rte.net.pxlen || ipa_nonzero(rte.next_hop)))
SKIP("RIPv1 reserved field is nonzero");
rte.tag = 0;
rte.pxlen = ip4_masklen(ip4_class_mask(ipa_to_ip4(rte.prefix)));
rte.net.pxlen = ip4_masklen(ip4_class_mask(net4_prefix(&rte.net)));
rte.next_hop = IPA_NONE;
}
if ((rte.pxlen < 0) || (rte.pxlen > MAX_PREFIX_LENGTH))
if (rte.net.pxlen == 255)
SKIP("invalid prefix length");
net_normalize(&rte.net);
int c = net_classify(&rte.net);
if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
SKIP("invalid prefix");
if (rte.metric > p->infinity)
SKIP("invalid metric");
@@ -604,7 +606,7 @@ rip_receive_response(struct rip_proto *p, struct rip_iface *ifa, struct rip_pack
rte.next_hop = IPA_NONE;
}
// TRACE(D_PACKETS, " %I/%d -> %I metric %d", rte.prefix, rte.pxlen, rte.next_hop, rte.metric);
// TRACE(D_PACKETS, " %N -> %I metric %d", &rte.net.n, rte.next_hop, rte.metric);
rte.metric += ifa->cf->metric;
@@ -618,16 +620,16 @@ rip_receive_response(struct rip_proto *p, struct rip_iface *ifa, struct rip_pack
.expires = now + ifa->cf->timeout_time
};
rip_update_rte(p, &rte.prefix, rte.pxlen, &new);
rip_update_rte(p, &rte.net, &new);
}
else
rip_withdraw_rte(p, &rte.prefix, rte.pxlen, from);
rip_withdraw_rte(p, &rte.net, from);
continue;
skip:
LOG_RTE("Ignoring route %I/%d received from %I - %s",
rte.prefix, rte.pxlen, from->nbr->addr, err_dsc);
LOG_RTE("Ignoring route %N received from %I - %s",
&rte.net, from->nbr->addr, err_dsc);
}
}

View File

@@ -92,15 +92,6 @@ static void rip_trigger_update(struct rip_proto *p);
* RIP routes
*/
static void
rip_init_entry(struct fib_node *fn)
{
// struct rip_entry *en = (void) *fn;
const uint offset = OFFSETOF(struct rip_entry, routes);
memset((byte *)fn + offset, 0, sizeof(struct rip_entry) - offset);
}
static struct rip_rte *
rip_add_rte(struct rip_proto *p, struct rip_rte **rp, struct rip_rte *src)
{
@@ -152,7 +143,7 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
if (rt)
{
/* Update */
net *n = net_get(p->p.table, en->n.prefix, en->n.pxlen);
net *n = net_get(p->p.table, en->n.addr);
rta a0 = {
.src = p->p.main_source,
@@ -221,7 +212,7 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
else
{
/* Withdraw */
net *n = net_find(p->p.table, en->n.prefix, en->n.pxlen);
net *n = net_find(p->p.table, en->n.addr);
rte_update(&p->p, n, NULL);
}
}
@@ -229,8 +220,7 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
/**
* rip_update_rte - enter a route update to RIP routing table
* @p: RIP instance
* @prefix: network prefix
* @pxlen: network prefix length
* @addr: network address
* @new: a &rip_rte representing the new route
*
* The function is called by the RIP packet processing code whenever it receives
@@ -240,9 +230,9 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
* rip_withdraw_rte() should be called instead of rip_update_rte().
*/
void
rip_update_rte(struct rip_proto *p, ip_addr *prefix, int pxlen, struct rip_rte *new)
rip_update_rte(struct rip_proto *p, net_addr *n, struct rip_rte *new)
{
struct rip_entry *en = fib_get(&p->rtable, prefix, pxlen);
struct rip_entry *en = fib_get(&p->rtable, n);
struct rip_rte *rt, **rp;
int changed = 0;
@@ -282,8 +272,7 @@ rip_update_rte(struct rip_proto *p, ip_addr *prefix, int pxlen, struct rip_rte *
/**
* rip_withdraw_rte - enter a route withdraw to RIP routing table
* @p: RIP instance
* @prefix: network prefix
* @pxlen: network prefix length
* @addr: network address
* @from: a &rip_neighbor propagating the withdraw
*
* The function is called by the RIP packet processing code whenever it receives
@@ -291,9 +280,9 @@ rip_update_rte(struct rip_proto *p, ip_addr *prefix, int pxlen, struct rip_rte *
* removed. Eventually, the change is also propagated by rip_announce_rte().
*/
void
rip_withdraw_rte(struct rip_proto *p, ip_addr *prefix, int pxlen, struct rip_neighbor *from)
rip_withdraw_rte(struct rip_proto *p, net_addr *n, struct rip_neighbor *from)
{
struct rip_entry *en = fib_find(&p->rtable, prefix, pxlen);
struct rip_entry *en = fib_find(&p->rtable, n);
struct rip_rte *rt, **rp;
if (!en)
@@ -335,15 +324,15 @@ rip_rt_notify(struct proto *P, struct rtable *table UNUSED, struct network *net,
if (rt_metric > p->infinity)
{
log(L_WARN "%s: Invalid rip_metric value %u for route %I/%d",
p->p.name, rt_metric, net->n.prefix, net->n.pxlen);
log(L_WARN "%s: Invalid rip_metric value %u for route %N",
p->p.name, rt_metric, net->n.addr);
rt_metric = p->infinity;
}
if (rt_tag > 0xffff)
{
log(L_WARN "%s: Invalid rip_tag value %u for route %I/%d",
p->p.name, rt_tag, net->n.prefix, net->n.pxlen);
log(L_WARN "%s: Invalid rip_tag value %u for route %N",
p->p.name, rt_tag, net->n.addr);
rt_metric = p->infinity;
rt_tag = 0;
}
@@ -355,7 +344,7 @@ rip_rt_notify(struct proto *P, struct rtable *table UNUSED, struct network *net,
* collection.
*/
en = fib_get(&p->rtable, &net->n.prefix, net->n.pxlen);
en = fib_get(&p->rtable, net->n.addr);
old_metric = en->valid ? en->metric : -1;
@@ -369,7 +358,7 @@ rip_rt_notify(struct proto *P, struct rtable *table UNUSED, struct network *net,
else
{
/* Withdraw */
en = fib_find(&p->rtable, &net->n.prefix, net->n.pxlen);
en = fib_find(&p->rtable, net->n.addr);
if (!en || en->valid != RIP_ENTRY_VALID)
return;
@@ -875,7 +864,7 @@ rip_timer(timer *t)
if (expires <= now)
{
// TRACE(D_EVENTS, "entry is too old: %I/%d", en->n.prefix, en->n.pxlen);
// TRACE(D_EVENTS, "entry is too old: %N", en->n.addr);
en->valid = 0;
}
else
@@ -1108,7 +1097,8 @@ rip_start(struct proto *P)
struct rip_config *cf = (void *) (P->cf);
init_list(&p->iface_list);
fib_init(&p->rtable, P->pool, sizeof(struct rip_entry), 0, rip_init_entry);
fib_init(&p->rtable, P->pool, rip_is_v2(p) ? NET_IP4 : NET_IP6,
sizeof(struct rip_entry), OFFSETOF(struct rip_entry, n), 0, NULL);
p->rte_slab = sl_new(P->pool, sizeof(struct rip_rte));
p->timer = tm_new_set(P->pool, rip_timer, p, 0, 0);
@@ -1257,8 +1247,8 @@ rip_dump(struct proto *P)
FIB_WALK(&p->rtable, e)
{
struct rip_entry *en = (struct rip_entry *) e;
debug("RIP: entry #%d: %I/%d via %I dev %s valid %d metric %d age %d s\n",
i++, en->n.prefix, en->n.pxlen, en->next_hop, en->iface->name,
debug("RIP: entry #%d: %N via %I dev %s valid %d metric %d age %d s\n",
i++, en->n.addr, en->next_hop, en->iface->name,
en->valid, en->metric, now - en->changed);
}
FIB_WALK_END;

View File

@@ -149,7 +149,6 @@ struct rip_neighbor
struct rip_entry
{
struct fib_node n;
struct rip_rte *routes; /* List of incoming routes */
u8 valid; /* Entry validity state (RIP_ENTRY_*) */
@@ -160,6 +159,8 @@ struct rip_entry
ip_addr next_hop; /* Outgoing route next hop */
bird_clock_t changed; /* Last time when the outgoing route metric changed */
struct fib_node n;
};
struct rip_rte
@@ -211,8 +212,8 @@ rip_reset_tx_session(struct rip_proto *p, struct rip_iface *ifa)
}
/* rip.c */
void rip_update_rte(struct rip_proto *p, ip_addr *prefix, int pxlen, struct rip_rte *new);
void rip_withdraw_rte(struct rip_proto *p, ip_addr *prefix, int pxlen, struct rip_neighbor *from);
void rip_update_rte(struct rip_proto *p, net_addr *n, struct rip_rte *new);
void rip_withdraw_rte(struct rip_proto *p, net_addr *n, struct rip_neighbor *from);
struct rip_neighbor * rip_get_neighbor(struct rip_proto *p, ip_addr *a, struct rip_iface *ifa);
void rip_update_bfd(struct rip_proto *p, struct rip_neighbor *n);
void rip_show_interfaces(struct proto *P, char *iff);