summaryrefslogtreecommitdiff
path: root/proto/babel
diff options
context:
space:
mode:
authorOndrej Zajicek (work) <santiago@crfreenet.org>2017-06-09 13:00:20 +0200
committerOndrej Zajicek (work) <santiago@crfreenet.org>2017-06-09 13:00:20 +0200
commitb3c6273efaa15976cc1290f00d5abde4991e184e (patch)
treedffce8bd491c0a535801077a854e6573d14f9d06 /proto/babel
parent300bd0eb85d14523ea7f0a7a3a4d92184f3c4fb3 (diff)
Babel: Implement IPv6 prefix compression on outgoing updates
Previously, the Babel protocol would never use prefix compression on outgoing updates (but would parse it on incoming ones). This adds compression of IPv6 addresses of outgoing updates. The compression only works to the extent that the FIB is walked in lexicographic order; i.e. a prefix is only compressed if it shares bytes with the previous prefix in the same packet. Thanks to Toke Høiland-Jørgensen <toke@toke.dk> for the patch.
Diffstat (limited to 'proto/babel')
-rw-r--r--proto/babel/packets.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/proto/babel/packets.c b/proto/babel/packets.c
index b52c2ddf..72ac4f29 100644
--- a/proto/babel/packets.c
+++ b/proto/babel/packets.c
@@ -133,6 +133,8 @@ struct babel_write_state {
u8 router_id_seen;
ip_addr next_hop_ip4;
ip_addr next_hop_ip6;
+ u8 def_ip6_prefix[16]; /* Implicit IPv6 prefix in network order */
+ u8 def_ip6_pxlen;
};
@@ -150,6 +152,14 @@ struct babel_write_state {
#define NET_SIZE(n) BYTES(net_pxlen(n))
+static inline uint
+bytes_equal(u8 *b1, u8 *b2, uint maxlen)
+{
+ uint i;
+ for (i = 0; (i < maxlen) && (*b1 == *b2); i++, b1++, b2++)
+ ;
+ return i;
+}
static inline u16
get_time16(const void *p)
@@ -696,7 +706,29 @@ babel_write_update(struct babel_tlv *hdr, union babel_msg *m,
{
tlv->ae = BABEL_AE_IP6;
tlv->plen = net6_pxlen(&msg->net);
- put_ip6_px(tlv->addr, &msg->net);
+
+ /* Address compression - omit initial matching bytes */
+ u8 buf[16], omit;
+ put_ip6(buf, net6_prefix(&msg->net));
+ omit = bytes_equal(buf, state->def_ip6_prefix,
+ MIN(tlv->plen, state->def_ip6_pxlen) / 8);
+
+ if (omit > 0)
+ {
+ memcpy(tlv->addr, buf + omit, NET_SIZE(&msg->net) - omit);
+
+ tlv->omitted = omit;
+ tlv->length -= omit;
+ len -= omit;
+ }
+ else
+ {
+ put_ip6_px(tlv->addr, &msg->net);
+ tlv->flags |= BABEL_FLAG_DEF_PREFIX;
+
+ put_ip6(state->def_ip6_prefix, net6_prefix(&msg->net));
+ state->def_ip6_pxlen = tlv->plen;
+ }
}
put_time16(&tlv->interval, msg->interval);