While changing log_addr() I noticed that struct bgpd_addr could benefit from changing the encoding of AID_VPN_IPv4 and AID_VPN_IPv6 addrs. Instead of having independent route distinguishers and labelstacks use common fields for those and use the v4 and v6 addresses for the prefix. This is a bit more compact but also simplifies some code since the handling of AID_VPN_IPv4 and AID_VPN_IPv6 can be handled in the same switch case.
I reduced the labelstack size from 21 to 18 (6 instead of 7 labels). Now in theory you could pack 7 labels into an IPv4 VPN NLRI (8bit prefixlen + 64bit RD + 16bit prefix + 21 * 8bit label = 256) but that is quite silly. Even 6 labels is more than enough. bgpd itself only allows a single MPLS label when announcing such networks. -- :wq Claudio PS: diff is based of /usr/src/usr.sbin Index: bgpctl/mrtparser.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpctl/mrtparser.c,v retrieving revision 1.13 diff -u -p -r1.13 mrtparser.c --- bgpctl/mrtparser.c 3 Jul 2019 06:22:01 -0000 1.13 +++ bgpctl/mrtparser.c 5 Jan 2021 10:05:30 -0000 @@ -833,14 +833,14 @@ mrt_extract_attr(struct mrt_rib_entry *r re->nexthop.aid = aid; memcpy(&tmp, a + 1 + sizeof(u_int64_t), sizeof(tmp)); - re->nexthop.vpn4.addr.s_addr = tmp; + re->nexthop.v4.s_addr = tmp; break; case AID_VPN_IPv6: if (attr_len < sizeof(u_int64_t) + sizeof(struct in6_addr)) return (-1); re->nexthop.aid = aid; - memcpy(&re->nexthop.vpn6.addr, + memcpy(&re->nexthop.v6, a + 1 + sizeof(u_int64_t), sizeof(struct in6_addr)); break; @@ -979,7 +979,7 @@ mrt_extract_addr(void *msg, u_int len, s return (-1); addr->aid = aid; /* XXX labelstack and rd missing */ - memcpy(&addr->vpn4.addr, b + sizeof(u_int64_t), + memcpy(&addr->v4, b + sizeof(u_int64_t), sizeof(struct in_addr)); return (sizeof(u_int64_t) + sizeof(struct in_addr)); case AID_VPN_IPv6: @@ -987,7 +987,7 @@ mrt_extract_addr(void *msg, u_int len, s return (-1); addr->aid = aid; /* XXX labelstack and rd missing */ - memcpy(&addr->vpn6.addr, b + sizeof(u_int64_t), + memcpy(&addr->v6, b + sizeof(u_int64_t), sizeof(struct in6_addr)); return (sizeof(u_int64_t) + sizeof(struct in6_addr)); default: Index: bgpd/bgpd.h =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v retrieving revision 1.409 diff -u -p -r1.409 bgpd.h --- bgpd/bgpd.h 4 Jan 2021 13:40:32 -0000 1.409 +++ bgpd/bgpd.h 5 Jan 2021 10:05:30 -0000 @@ -176,23 +176,6 @@ extern const struct aid aid_vals[]; sizeof(struct pt_entry_vpn6) \ } -struct vpn4_addr { - u_int64_t rd; - struct in_addr addr; - u_int8_t labelstack[21]; /* max that makes sense */ - u_int8_t labellen; - u_int8_t pad1; - u_int8_t pad2; -}; - -struct vpn6_addr { - u_int64_t rd; - struct in6_addr addr; - u_int8_t labelstack[21]; /* max that makes sense */ - u_int8_t labellen; - u_int8_t pad1; - u_int8_t pad2; -}; #define BGP_MPLS_BOS 0x01 @@ -200,22 +183,15 @@ struct bgpd_addr { union { struct in_addr v4; struct in6_addr v6; - struct vpn4_addr vpn4; - struct vpn6_addr vpn6; /* maximum size for a prefix is 256 bits */ - u_int8_t addr8[32]; - u_int16_t addr16[16]; - u_int32_t addr32[8]; } ba; /* 128-bit address */ + u_int64_t rd; /* route distinguisher for VPN addrs */ u_int32_t scope_id; /* iface scope id for v6 */ u_int8_t aid; + u_int8_t labellen; /* size of the labelstack */ + u_int8_t labelstack[18]; /* max that makes sense */ #define v4 ba.v4 #define v6 ba.v6 -#define vpn4 ba.vpn4 -#define vpn6 ba.vpn6 -#define addr8 ba.addr8 -#define addr16 ba.addr16 -#define addr32 ba.addr32 }; #define DEFAULT_LISTENER 0x01 Index: bgpd/kroute.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/kroute.c,v retrieving revision 1.240 diff -u -p -r1.240 kroute.c --- bgpd/kroute.c 29 Dec 2020 09:20:25 -0000 1.240 +++ bgpd/kroute.c 5 Jan 2021 10:05:30 -0000 @@ -601,14 +601,14 @@ krVPN4_change(struct ktable *kt, struct return (0); /* only single MPLS label are supported for now */ - if (kl->prefix.vpn4.labellen != 3) { + if (kl->prefix.labellen != 3) { log_warnx("%s: %s/%u has not a single label", __func__, log_addr(&kl->prefix), kl->prefixlen); return (0); } - mplslabel = (kl->prefix.vpn4.labelstack[0] << 24) | - (kl->prefix.vpn4.labelstack[1] << 16) | - (kl->prefix.vpn4.labelstack[2] << 8); + mplslabel = (kl->prefix.labelstack[0] << 24) | + (kl->prefix.labelstack[1] << 16) | + (kl->prefix.labelstack[2] << 8); mplslabel = htonl(mplslabel); labelid = rtlabel_name2id(kl->label); @@ -617,7 +617,7 @@ krVPN4_change(struct ktable *kt, struct if (kl->flags & (F_BLACKHOLE|F_REJECT)) kl->nexthop.v4.s_addr = htonl(INADDR_LOOPBACK); - if ((kr = kroute_find(kt, kl->prefix.vpn4.addr.s_addr, kl->prefixlen, + if ((kr = kroute_find(kt, kl->prefix.v4.s_addr, kl->prefixlen, fib_prio)) != NULL) action = RTM_CHANGE; @@ -626,7 +626,7 @@ krVPN4_change(struct ktable *kt, struct log_warn("%s", __func__); return (-1); } - kr->r.prefix.s_addr = kl->prefix.vpn4.addr.s_addr; + kr->r.prefix.s_addr = kl->prefix.v4.s_addr; kr->r.prefixlen = kl->prefixlen; kr->r.nexthop.s_addr = kl->nexthop.v4.s_addr; kr->r.flags = kl->flags | F_BGPD_INSERTED | F_MPLS; @@ -675,14 +675,14 @@ krVPN6_change(struct ktable *kt, struct return (0); /* only single MPLS label are supported for now */ - if (kl->prefix.vpn6.labellen != 3) { + if (kl->prefix.labellen != 3) { log_warnx("%s: %s/%u has not a single label", __func__, log_addr(&kl->prefix), kl->prefixlen); return (0); } - mplslabel = (kl->prefix.vpn6.labelstack[0] << 24) | - (kl->prefix.vpn6.labelstack[1] << 16) | - (kl->prefix.vpn6.labelstack[2] << 8); + mplslabel = (kl->prefix.labelstack[0] << 24) | + (kl->prefix.labelstack[1] << 16) | + (kl->prefix.labelstack[2] << 8); mplslabel = htonl(mplslabel); /* for blackhole and reject routes nexthop needs to be ::1 */ @@ -691,7 +691,7 @@ krVPN6_change(struct ktable *kt, struct labelid = rtlabel_name2id(kl->label); - if ((kr6 = kroute6_find(kt, &kl->prefix.vpn6.addr, kl->prefixlen, + if ((kr6 = kroute6_find(kt, &kl->prefix.v6, kl->prefixlen, fib_prio)) != NULL) action = RTM_CHANGE; @@ -700,8 +700,7 @@ krVPN6_change(struct ktable *kt, struct log_warn("%s", __func__); return (-1); } - memcpy(&kr6->r.prefix, &kl->prefix.vpn6.addr, - sizeof(struct in6_addr)); + memcpy(&kr6->r.prefix, &kl->prefix.v6, sizeof(struct in6_addr)); kr6->r.prefixlen = kl->prefixlen; memcpy(&kr6->r.nexthop, &kl->nexthop.v6, sizeof(struct in6_addr)); @@ -848,7 +847,7 @@ krVPN4_delete(struct ktable *kt, struct { struct kroute_node *kr; - if ((kr = kroute_find(kt, kl->prefix.vpn4.addr.s_addr, kl->prefixlen, + if ((kr = kroute_find(kt, kl->prefix.v4.s_addr, kl->prefixlen, fib_prio)) == NULL) return (0); @@ -871,7 +870,7 @@ krVPN6_delete(struct ktable *kt, struct { struct kroute6_node *kr6; - if ((kr6 = kroute6_find(kt, &kl->prefix.vpn6.addr, kl->prefixlen, + if ((kr6 = kroute6_find(kt, &kl->prefix.v6, kl->prefixlen, fib_prio)) == NULL) return (0); Index: bgpd/rde.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v retrieving revision 1.510 diff -u -p -r1.510 rde.c --- bgpd/rde.c 30 Dec 2020 07:29:56 -0000 1.510 +++ bgpd/rde.c 5 Jan 2021 10:05:31 -0000 @@ -3642,7 +3642,7 @@ network_add(struct network_config *nc, s { struct l3vpn *vpn; struct filter_set_head *vpnset = NULL; - in_addr_t prefix4; + struct in_addr prefix4; struct in6_addr prefix6; u_int8_t vstate; u_int16_t i; @@ -3653,37 +3653,35 @@ network_add(struct network_config *nc, s continue; switch (nc->prefix.aid) { case AID_INET: - prefix4 = nc->prefix.v4.s_addr; - bzero(&nc->prefix, sizeof(nc->prefix)); + prefix4 = nc->prefix.v4; + memset(&nc->prefix, 0, sizeof(nc->prefix)); nc->prefix.aid = AID_VPN_IPv4; - nc->prefix.vpn4.rd = vpn->rd; - nc->prefix.vpn4.addr.s_addr = prefix4; - nc->prefix.vpn4.labellen = 3; - nc->prefix.vpn4.labelstack[0] = + nc->prefix.rd = vpn->rd; + nc->prefix.v4 = prefix4; + nc->prefix.labellen = 3; + nc->prefix.labelstack[0] = (vpn->label >> 12) & 0xff; - nc->prefix.vpn4.labelstack[1] = + nc->prefix.labelstack[1] = (vpn->label >> 4) & 0xff; - nc->prefix.vpn4.labelstack[2] = + nc->prefix.labelstack[2] = (vpn->label << 4) & 0xf0; - nc->prefix.vpn4.labelstack[2] |= BGP_MPLS_BOS; + nc->prefix.labelstack[2] |= BGP_MPLS_BOS; vpnset = &vpn->export; break; case AID_INET6: - memcpy(&prefix6, &nc->prefix.v6.s6_addr, - sizeof(struct in6_addr)); + prefix6 = nc->prefix.v6; memset(&nc->prefix, 0, sizeof(nc->prefix)); nc->prefix.aid = AID_VPN_IPv6; - nc->prefix.vpn6.rd = vpn->rd; - memcpy(&nc->prefix.vpn6.addr.s6_addr, &prefix6, - sizeof(struct in6_addr)); - nc->prefix.vpn6.labellen = 3; - nc->prefix.vpn6.labelstack[0] = + nc->prefix.rd = vpn->rd; + nc->prefix.v6 = prefix6; + nc->prefix.labellen = 3; + nc->prefix.labelstack[0] = (vpn->label >> 12) & 0xff; - nc->prefix.vpn6.labelstack[1] = + nc->prefix.labelstack[1] = (vpn->label >> 4) & 0xff; - nc->prefix.vpn6.labelstack[2] = + nc->prefix.labelstack[2] = (vpn->label << 4) & 0xf0; - nc->prefix.vpn6.labelstack[2] |= BGP_MPLS_BOS; + nc->prefix.labelstack[2] |= BGP_MPLS_BOS; vpnset = &vpn->export; break; default: @@ -3729,7 +3727,7 @@ void network_delete(struct network_config *nc) { struct l3vpn *vpn; - in_addr_t prefix4; + struct in_addr prefix4; struct in6_addr prefix6; u_int32_t i; @@ -3739,36 +3737,34 @@ network_delete(struct network_config *nc continue; switch (nc->prefix.aid) { case AID_INET: - prefix4 = nc->prefix.v4.s_addr; - bzero(&nc->prefix, sizeof(nc->prefix)); + prefix4 = nc->prefix.v4; + memset(&nc->prefix, 0, sizeof(nc->prefix)); nc->prefix.aid = AID_VPN_IPv4; - nc->prefix.vpn4.rd = vpn->rd; - nc->prefix.vpn4.addr.s_addr = prefix4; - nc->prefix.vpn4.labellen = 3; - nc->prefix.vpn4.labelstack[0] = + nc->prefix.rd = vpn->rd; + nc->prefix.v4 = prefix4; + nc->prefix.labellen = 3; + nc->prefix.labelstack[0] = (vpn->label >> 12) & 0xff; - nc->prefix.vpn4.labelstack[1] = + nc->prefix.labelstack[1] = (vpn->label >> 4) & 0xff; - nc->prefix.vpn4.labelstack[2] = + nc->prefix.labelstack[2] = (vpn->label << 4) & 0xf0; - nc->prefix.vpn4.labelstack[2] |= BGP_MPLS_BOS; + nc->prefix.labelstack[2] |= BGP_MPLS_BOS; break; case AID_INET6: - memcpy(&prefix6, &nc->prefix.v6.s6_addr, - sizeof(struct in6_addr)); + prefix6 = nc->prefix.v6; memset(&nc->prefix, 0, sizeof(nc->prefix)); nc->prefix.aid = AID_VPN_IPv6; - nc->prefix.vpn6.rd = vpn->rd; - memcpy(&nc->prefix.vpn6.addr.s6_addr, &prefix6, - sizeof(struct in6_addr)); - nc->prefix.vpn6.labellen = 3; - nc->prefix.vpn6.labelstack[0] = + nc->prefix.rd = vpn->rd; + nc->prefix.v6 = prefix6; + nc->prefix.labellen = 3; + nc->prefix.labelstack[0] = (vpn->label >> 12) & 0xff; - nc->prefix.vpn6.labelstack[1] = + nc->prefix.labelstack[1] = (vpn->label >> 4) & 0xff; - nc->prefix.vpn6.labelstack[2] = + nc->prefix.labelstack[2] = (vpn->label << 4) & 0xf0; - nc->prefix.vpn6.labelstack[2] |= BGP_MPLS_BOS; + nc->prefix.labelstack[2] |= BGP_MPLS_BOS; break; default: log_warnx("unable to VPNize prefix"); Index: bgpd/rde_prefix.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde_prefix.c,v retrieving revision 1.39 diff -u -p -r1.39 rde_prefix.c --- bgpd/rde_prefix.c 1 Jul 2019 07:07:08 -0000 1.39 +++ bgpd/rde_prefix.c 5 Jan 2021 10:05:31 -0000 @@ -79,27 +79,24 @@ pt_getaddr(struct pt_entry *pte, struct addr->v4 = ((struct pt_entry4 *)pte)->prefix4; break; case AID_INET6: - memcpy(&addr->v6, &((struct pt_entry6 *)pte)->prefix6, - sizeof(addr->v6)); + addr->v6 = ((struct pt_entry6 *)pte)->prefix6; /* XXX scope_id ??? */ break; case AID_VPN_IPv4: - addr->vpn4.addr = ((struct pt_entry_vpn4 *)pte)->prefix4; - addr->vpn4.rd = ((struct pt_entry_vpn4 *)pte)->rd; - addr->vpn4.labellen = ((struct pt_entry_vpn4 *)pte)->labellen; - memcpy(addr->vpn4.labelstack, + addr->v4 = ((struct pt_entry_vpn4 *)pte)->prefix4; + addr->rd = ((struct pt_entry_vpn4 *)pte)->rd; + addr->labellen = ((struct pt_entry_vpn4 *)pte)->labellen; + memcpy(addr->labelstack, ((struct pt_entry_vpn4 *)pte)->labelstack, - addr->vpn4.labellen); + addr->labellen); break; case AID_VPN_IPv6: - memcpy(&addr->vpn6.addr, - &((struct pt_entry_vpn6 *)pte)->prefix6, - sizeof(addr->vpn6.addr)); - addr->vpn6.rd = ((struct pt_entry_vpn6 *)pte)->rd; - addr->vpn6.labellen = ((struct pt_entry_vpn6 *)pte)->labellen; - memcpy(addr->vpn6.labelstack, + addr->v6 = ((struct pt_entry_vpn6 *)pte)->prefix6; + addr->rd = ((struct pt_entry_vpn6 *)pte)->rd; + addr->labellen = ((struct pt_entry_vpn6 *)pte)->labellen; + memcpy(addr->labelstack, ((struct pt_entry_vpn6 *)pte)->labelstack, - addr->vpn6.labellen); + addr->labellen); break; default: fatalx("pt_getaddr: unknown af"); @@ -136,26 +133,24 @@ pt_fill(struct bgpd_addr *prefix, int pr pte_vpn4.aid = prefix->aid; if (prefixlen > 32) fatalx("pt_fill: bad IPv4 prefixlen"); - inet4applymask(&pte_vpn4.prefix4, &prefix->vpn4.addr, - prefixlen); + inet4applymask(&pte_vpn4.prefix4, &prefix->v4, prefixlen); pte_vpn4.prefixlen = prefixlen; - pte_vpn4.rd = prefix->vpn4.rd; - pte_vpn4.labellen = prefix->vpn4.labellen; - memcpy(pte_vpn4.labelstack, prefix->vpn4.labelstack, - prefix->vpn4.labellen); + pte_vpn4.rd = prefix->rd; + pte_vpn4.labellen = prefix->labellen; + memcpy(pte_vpn4.labelstack, prefix->labelstack, + prefix->labellen); return ((struct pt_entry *)&pte_vpn4); case AID_VPN_IPv6: memset(&pte_vpn6, 0, sizeof(pte_vpn6)); pte_vpn6.aid = prefix->aid; if (prefixlen > 128) fatalx("pt_get: bad IPv6 prefixlen"); - inet6applymask(&pte_vpn6.prefix6, &prefix->vpn6.addr, - prefixlen); + inet6applymask(&pte_vpn6.prefix6, &prefix->v6, prefixlen); pte_vpn6.prefixlen = prefixlen; - pte_vpn6.rd = prefix->vpn6.rd; - pte_vpn6.labellen = prefix->vpn6.labellen; - memcpy(pte_vpn6.labelstack, prefix->vpn6.labelstack, - prefix->vpn6.labellen); + pte_vpn6.rd = prefix->rd; + pte_vpn6.labellen = prefix->labellen; + memcpy(pte_vpn6.labelstack, prefix->labelstack, + prefix->labellen); return ((struct pt_entry *)&pte_vpn6); default: fatalx("pt_fill: unknown af"); Index: bgpd/rde_rib.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde_rib.c,v retrieving revision 1.218 diff -u -p -r1.218 rde_rib.c --- bgpd/rde_rib.c 4 Dec 2020 11:57:13 -0000 1.218 +++ bgpd/rde_rib.c 5 Jan 2021 10:05:31 -0000 @@ -1417,47 +1417,19 @@ prefix_write(u_char *buf, int len, struc memcpy(buf, &prefix->ba, totlen - 1); return (totlen); case AID_VPN_IPv4: - totlen = PREFIX_SIZE(plen) + sizeof(prefix->vpn4.rd); - psize = PREFIX_SIZE(plen) - 1; - plen += sizeof(prefix->vpn4.rd) * 8; - if (withdraw) { - /* withdraw have one compat label as placeholder */ - totlen += 3; - plen += 3 * 8; - } else { - totlen += prefix->vpn4.labellen; - plen += prefix->vpn4.labellen * 8; - } - - if (totlen > len) - return (-1); - *buf++ = plen; - if (withdraw) { - /* magic compatibility label as per rfc8277 */ - *buf++ = 0x80; - *buf++ = 0x0; - *buf++ = 0x0; - } else { - memcpy(buf, &prefix->vpn4.labelstack, - prefix->vpn4.labellen); - buf += prefix->vpn4.labellen; - } - memcpy(buf, &prefix->vpn4.rd, sizeof(prefix->vpn4.rd)); - buf += sizeof(prefix->vpn4.rd); - memcpy(buf, &prefix->vpn4.addr, psize); - return (totlen); case AID_VPN_IPv6: - totlen = PREFIX_SIZE(plen) + sizeof(prefix->vpn6.rd); + totlen = PREFIX_SIZE(plen) + sizeof(prefix->rd); psize = PREFIX_SIZE(plen) - 1; - plen += sizeof(prefix->vpn6.rd) * 8; + plen += sizeof(prefix->rd) * 8; if (withdraw) { /* withdraw have one compat label as placeholder */ totlen += 3; plen += 3 * 8; } else { - totlen += prefix->vpn6.labellen; - plen += prefix->vpn6.labellen * 8; + totlen += prefix->labellen; + plen += prefix->labellen * 8; } + if (totlen > len) return (-1); *buf++ = plen; @@ -1467,13 +1439,13 @@ prefix_write(u_char *buf, int len, struc *buf++ = 0x0; *buf++ = 0x0; } else { - memcpy(buf, &prefix->vpn6.labelstack, - prefix->vpn6.labellen); - buf += prefix->vpn6.labellen; + memcpy(buf, &prefix->labelstack, + prefix->labellen); + buf += prefix->labellen; } - memcpy(buf, &prefix->vpn6.rd, sizeof(prefix->vpn6.rd)); - buf += sizeof(prefix->vpn6.rd); - memcpy(buf, &prefix->vpn6.addr, psize); + memcpy(buf, &prefix->rd, sizeof(prefix->rd)); + buf += sizeof(prefix->rd); + memcpy(buf, &prefix->ba, psize); return (totlen); default: return (-1); @@ -1492,12 +1464,9 @@ prefix_writebuf(struct ibuf *buf, struct totlen = PREFIX_SIZE(plen); break; case AID_VPN_IPv4: - totlen = PREFIX_SIZE(plen) + sizeof(prefix->vpn4.rd) + - prefix->vpn4.labellen; - break; case AID_VPN_IPv6: - totlen = PREFIX_SIZE(plen) + sizeof(prefix->vpn6.rd) + - prefix->vpn6.labellen; + totlen = PREFIX_SIZE(plen) + sizeof(prefix->rd) + + prefix->labellen; break; default: return (-1); Index: bgpd/util.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/util.c,v retrieving revision 1.58 diff -u -p -r1.58 util.c --- bgpd/util.c 5 Jan 2021 10:00:28 -0000 1.58 +++ bgpd/util.c 5 Jan 2021 10:05:31 -0000 @@ -47,11 +47,8 @@ log_addr(const struct bgpd_addr *addr) case AID_INET6: return log_sockaddr(sa, len); case AID_VPN_IPv4: - snprintf(buf, sizeof(buf), "%s %s", log_rd(addr->vpn4.rd), - log_sockaddr(sa, len)); - return (buf); case AID_VPN_IPv6: - snprintf(buf, sizeof(buf), "%s %s", log_rd(addr->vpn6.rd), + snprintf(buf, sizeof(buf), "%s %s", log_rd(addr->rd), log_sockaddr(sa, len)); return (buf); } @@ -532,8 +529,8 @@ nlri_get_vpn4(u_char *p, u_int16_t len, do { if (len - plen < 3 || pfxlen < 3 * 8) return (-1); - if (prefix->vpn4.labellen + 3U > - sizeof(prefix->vpn4.labelstack)) + if (prefix->labellen + 3U > + sizeof(prefix->labelstack)) return (-1); if (withdraw) { /* on withdraw ignore the labelstack all together */ @@ -541,13 +538,13 @@ nlri_get_vpn4(u_char *p, u_int16_t len, pfxlen -= 3 * 8; break; } - prefix->vpn4.labelstack[prefix->vpn4.labellen++] = *p++; - prefix->vpn4.labelstack[prefix->vpn4.labellen++] = *p++; - prefix->vpn4.labelstack[prefix->vpn4.labellen] = *p++; - if (prefix->vpn4.labelstack[prefix->vpn4.labellen] & + prefix->labelstack[prefix->labellen++] = *p++; + prefix->labelstack[prefix->labellen++] = *p++; + prefix->labelstack[prefix->labellen] = *p++; + if (prefix->labelstack[prefix->labellen] & BGP_MPLS_BOS) done = 1; - prefix->vpn4.labellen++; + prefix->labellen++; plen += 3; pfxlen -= 3 * 8; } while (!done); @@ -556,7 +553,7 @@ nlri_get_vpn4(u_char *p, u_int16_t len, if (len - plen < (int)sizeof(u_int64_t) || pfxlen < sizeof(u_int64_t) * 8) return (-1); - memcpy(&prefix->vpn4.rd, p, sizeof(u_int64_t)); + memcpy(&prefix->rd, p, sizeof(u_int64_t)); pfxlen -= sizeof(u_int64_t) * 8; p += sizeof(u_int64_t); plen += sizeof(u_int64_t); @@ -567,8 +564,8 @@ nlri_get_vpn4(u_char *p, u_int16_t len, if (pfxlen > 32) return (-1); - if ((rv = extract_prefix(p, len, &prefix->vpn4.addr, - pfxlen, sizeof(prefix->vpn4.addr))) == -1) + if ((rv = extract_prefix(p, len, &prefix->v4, + pfxlen, sizeof(prefix->v4))) == -1) return (-1); return (plen + rv); @@ -595,8 +592,8 @@ nlri_get_vpn6(u_char *p, u_int16_t len, do { if (len - plen < 3 || pfxlen < 3 * 8) return (-1); - if (prefix->vpn6.labellen + 3U > - sizeof(prefix->vpn6.labelstack)) + if (prefix->labellen + 3U > + sizeof(prefix->labelstack)) return (-1); if (withdraw) { /* on withdraw ignore the labelstack all together */ @@ -605,13 +602,13 @@ nlri_get_vpn6(u_char *p, u_int16_t len, break; } - prefix->vpn6.labelstack[prefix->vpn6.labellen++] = *p++; - prefix->vpn6.labelstack[prefix->vpn6.labellen++] = *p++; - prefix->vpn6.labelstack[prefix->vpn6.labellen] = *p++; - if (prefix->vpn6.labelstack[prefix->vpn6.labellen] & + prefix->labelstack[prefix->labellen++] = *p++; + prefix->labelstack[prefix->labellen++] = *p++; + prefix->labelstack[prefix->labellen] = *p++; + if (prefix->labelstack[prefix->labellen] & BGP_MPLS_BOS) done = 1; - prefix->vpn6.labellen++; + prefix->labellen++; plen += 3; pfxlen -= 3 * 8; } while (!done); @@ -621,7 +618,7 @@ nlri_get_vpn6(u_char *p, u_int16_t len, pfxlen < sizeof(u_int64_t) * 8) return (-1); - memcpy(&prefix->vpn6.rd, p, sizeof(u_int64_t)); + memcpy(&prefix->rd, p, sizeof(u_int64_t)); pfxlen -= sizeof(u_int64_t) * 8; p += sizeof(u_int64_t); plen += sizeof(u_int64_t); @@ -633,8 +630,8 @@ nlri_get_vpn6(u_char *p, u_int16_t len, if (pfxlen > 128) return (-1); - if ((rv = extract_prefix(p, len, &prefix->vpn6.addr, - pfxlen, sizeof(prefix->vpn6.addr))) == -1) + if ((rv = extract_prefix(p, len, &prefix->v6, + pfxlen, sizeof(prefix->v6))) == -1) return (-1); return (plen + rv); @@ -658,6 +655,12 @@ prefix_compare(const struct bgpd_addr *a return (a->aid - b->aid); switch (a->aid) { + case AID_VPN_IPv4: + if (be64toh(a->rd) > be64toh(b->rd)) + return (1); + if (be64toh(a->rd) < be64toh(b->rd)) + return (-1); + /* FALLTHROUGH */ case AID_INET: if (prefixlen == 0) return (0); @@ -666,9 +669,17 @@ prefix_compare(const struct bgpd_addr *a mask = htonl(prefixlen2mask(prefixlen)); aa = ntohl(a->v4.s_addr & mask); ba = ntohl(b->v4.s_addr & mask); - if (aa != ba) - return (aa - ba); - return (0); + if (aa > ba) + return (1); + if (aa < ba) + return (1); + break; + case AID_VPN_IPv6: + if (be64toh(a->rd) > be64toh(b->rd)) + return (1); + if (be64toh(a->rd) < be64toh(b->rd)) + return (-1); + /* FALLTHROUGH */ case AID_INET6: if (prefixlen == 0) return (0); @@ -685,53 +696,20 @@ prefix_compare(const struct bgpd_addr *a return ((a->v6.s6_addr[prefixlen / 8] & m) - (b->v6.s6_addr[prefixlen / 8] & m)); } - return (0); - case AID_VPN_IPv4: - if (prefixlen > 32) - return (-1); - if (be64toh(a->vpn4.rd) > be64toh(b->vpn4.rd)) - return (1); - if (be64toh(a->vpn4.rd) < be64toh(b->vpn4.rd)) - return (-1); - mask = htonl(prefixlen2mask(prefixlen)); - aa = ntohl(a->vpn4.addr.s_addr & mask); - ba = ntohl(b->vpn4.addr.s_addr & mask); - if (aa != ba) - return (aa - ba); - if (a->vpn4.labellen > b->vpn4.labellen) - return (1); - if (a->vpn4.labellen < b->vpn4.labellen) - return (-1); - return (memcmp(a->vpn4.labelstack, b->vpn4.labelstack, - a->vpn4.labellen)); - case AID_VPN_IPv6: - if (prefixlen > 128) - return (-1); - if (be64toh(a->vpn6.rd) > be64toh(b->vpn6.rd)) - return (1); - if (be64toh(a->vpn6.rd) < be64toh(b->vpn6.rd)) - return (-1); - for (i = 0; i < prefixlen / 8; i++) - if (a->vpn6.addr.s6_addr[i] != b->vpn6.addr.s6_addr[i]) - return (a->vpn6.addr.s6_addr[i] - - b->vpn6.addr.s6_addr[i]); - i = prefixlen % 8; - if (i) { - m = 0xff00 >> i; - if ((a->vpn6.addr.s6_addr[prefixlen / 8] & m) != - (b->vpn6.addr.s6_addr[prefixlen / 8] & m)) - return ((a->vpn6.addr.s6_addr[prefixlen / 8] & - m) - (b->vpn6.addr.s6_addr[prefixlen / 8] & - m)); - } - if (a->vpn6.labellen > b->vpn6.labellen) + break; + default: + return (-1); + } + + if (a->aid == AID_VPN_IPv4 || a->aid == AID_VPN_IPv6) { + if (a->labellen > b->labellen) return (1); - if (a->vpn6.labellen < b->vpn6.labellen) + if (a->labellen < b->labellen) return (-1); - return (memcmp(a->vpn6.labelstack, b->vpn6.labelstack, - a->vpn6.labellen)); + return (memcmp(a->labelstack, b->labelstack, a->labellen)); } - return (-1); + return (0); + } in_addr_t @@ -847,28 +825,16 @@ addr2sa(const struct bgpd_addr *addr, u_ bzero(&ss, sizeof(ss)); switch (addr->aid) { case AID_INET: + case AID_VPN_IPv4: sa_in->sin_family = AF_INET; sa_in->sin_addr.s_addr = addr->v4.s_addr; sa_in->sin_port = htons(port); *len = sizeof(struct sockaddr_in); break; case AID_INET6: - sa_in6->sin6_family = AF_INET6; - memcpy(&sa_in6->sin6_addr, &addr->v6, - sizeof(sa_in6->sin6_addr)); - sa_in6->sin6_port = htons(port); - sa_in6->sin6_scope_id = addr->scope_id; - *len = sizeof(struct sockaddr_in6); - break; - case AID_VPN_IPv4: - sa_in->sin_family = AF_INET; - sa_in->sin_addr.s_addr = addr->vpn4.addr.s_addr; - sa_in->sin_port = htons(port); - *len = sizeof(struct sockaddr_in); - break; case AID_VPN_IPv6: sa_in6->sin6_family = AF_INET6; - memcpy(&sa_in6->sin6_addr, &addr->vpn6.addr, + memcpy(&sa_in6->sin6_addr, &addr->v6, sizeof(sa_in6->sin6_addr)); sa_in6->sin6_port = htons(port); sa_in6->sin6_scope_id = addr->scope_id;