summaryrefslogtreecommitdiff
path: root/proto
diff options
context:
space:
mode:
Diffstat (limited to 'proto')
-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);