This diff adds support to read MRT files using the new introduced _ADDPATH
types as defined in RFC8050. I also started adding MRT support to bgpd but
that depends on ADD-PATH itself.

There are a few gotchas, especially the MRT_DUMP_V2 RIB_GENERIC_ADDPATH
handling is different from all other RIB entry handling. This is a major
pain point for bgpd less so for the bgpctl parser.

Some MRT update dumps that can be downloaded and use ADDPATH do actually
use the BGP4MP_MESSAGE _ADDPATH variant for non-addpath enabled sessions.
The update messages can not be parsed because the NLRI encoding is incorrect.

I tested with a few RIB and UPDATE dumps from RIS, route-views and other
open collectors and it works for me.
-- 
:wq Claudio

Index: usr.sbin/bgpctl/bgpctl.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.c,v
retrieving revision 1.269
diff -u -p -r1.269 bgpctl.c
--- usr.sbin/bgpctl/bgpctl.c    16 Jun 2021 16:24:11 -0000      1.269
+++ usr.sbin/bgpctl/bgpctl.c    13 Jul 2021 13:20:51 -0000
@@ -470,7 +470,7 @@ show(struct imsg *imsg, struct parse_res
                        warnx("bad IMSG_CTL_SHOW_RIB_ATTR received");
                        break;
                }
-               output->attr(imsg->data, ilen, res->flags);
+               output->attr(imsg->data, ilen, res->flags, 0);
                break;
        case IMSG_CTL_SHOW_RIB_MEM:
                if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(stats))
@@ -1150,6 +1150,10 @@ show_mrt_dump(struct mrt_rib *mr, struct
                ctl.local_pref = mre->local_pref;
                ctl.med = mre->med;
                /* weight is not part of the mrt dump so it can't be set */
+               if (mr->add_path) {
+                       ctl.flags |= F_PREF_PATH_ID;
+                       ctl.path_id = mre->path_id;
+               }
 
                if (mre->peer_idx < mp->npeers) {
                        ctl.remote_addr = mp->peers[mre->peer_idx].addr;
@@ -1195,7 +1199,7 @@ show_mrt_dump(struct mrt_rib *mr, struct
                if (req->flags & F_CTL_DETAIL) {
                        for (j = 0; j < mre->nattrs; j++)
                                output->attr(mre->attrs[j].attr,
-                                   mre->attrs[j].attr_len, req->flags);
+                                   mre->attrs[j].attr_len, req->flags, 0);
                }
        }
 }
@@ -1211,6 +1215,10 @@ network_mrt_dump(struct mrt_rib *mr, str
        time_t                           now;
        u_int16_t                        i, j;
 
+       /* can't announce more than one path so ignore add-path */
+       if (mr->add_path)
+               return;
+
        now = time(NULL);
        for (i = 0; i < mr->nentries; i++) {
                mre = &mr->entries[i];
@@ -1586,10 +1594,11 @@ show_mrt_notification(u_char *p, u_int16
 
 /* XXX this function does not handle JSON output */
 static void
-show_mrt_update(u_char *p, u_int16_t len, int reqflags)
+show_mrt_update(u_char *p, u_int16_t len, int reqflags, int addpath)
 {
        struct bgpd_addr prefix;
        int pos;
+       u_int32_t pathid;
        u_int16_t wlen, alen;
        u_int8_t prefixlen;
 
@@ -1609,12 +1618,25 @@ show_mrt_update(u_char *p, u_int16_t len
        if (wlen > 0) {
                printf("\n     Withdrawn prefixes:");
                while (wlen > 0) {
+                       if (addpath) {
+                               if (wlen <= sizeof(pathid)) {
+                                       printf("bad withdraw prefix");
+                                       return;
+                               }
+                               memcpy(&pathid, p, sizeof(pathid));
+                               pathid = ntohl(pathid);
+                               p += sizeof(pathid);
+                               len -= sizeof(pathid);
+                               wlen -= sizeof(pathid);
+                       }
                        if ((pos = nlri_get_prefix(p, wlen, &prefix,
                            &prefixlen)) == -1) {
                                printf("bad withdraw prefix");
                                return;
                        }
                        printf(" %s/%u", log_addr(&prefix), prefixlen);
+                       if (addpath)
+                               printf(" path-id %u", pathid);
                        p += pos;
                        len -= pos;
                        wlen -= pos;
@@ -1655,7 +1677,7 @@ show_mrt_update(u_char *p, u_int16_t len
                        attrlen += 1 + 2;
                }
 
-               output->attr(p, attrlen, reqflags);
+               output->attr(p, attrlen, reqflags, addpath);
                p += attrlen;
                alen -= attrlen;
                len -= attrlen;
@@ -1664,12 +1686,24 @@ show_mrt_update(u_char *p, u_int16_t len
        if (len > 0) {
                printf("    NLRI prefixes:");
                while (len > 0) {
+                       if (addpath) {
+                               if (len <= sizeof(pathid)) {
+                                       printf(" bad nlri prefix: pathid, len 
%d", len);
+                                       return;
+                               }
+                               memcpy(&pathid, p, sizeof(pathid));
+                               pathid = ntohl(pathid);
+                               p += sizeof(pathid);
+                               len -= sizeof(pathid);
+                       }
                        if ((pos = nlri_get_prefix(p, len, &prefix,
                            &prefixlen)) == -1) {
-                               printf("bad withdraw prefix");
+                               printf(" bad nlri prefix");
                                return;
                        }
                        printf(" %s/%u", log_addr(&prefix), prefixlen);
+                       if (addpath)
+                               printf(" path-id %u", pathid);
                        p += pos;
                        len -= pos;
                }
@@ -1739,7 +1773,8 @@ show_mrt_msg(struct mrt_bgp_msg *mm, voi
                        printf("illegal length: %u byte\n", len);
                        return;
                }
-               show_mrt_update(p, len - MSGSIZE_HEADER, req->flags);
+               show_mrt_update(p, len - MSGSIZE_HEADER, req->flags,
+                   mm->add_path);
                break;
        case KEEPALIVE:
                printf("%s ", msgtypenames[type]);
Index: usr.sbin/bgpctl/bgpctl.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.h,v
retrieving revision 1.11
diff -u -p -r1.11 bgpctl.h
--- usr.sbin/bgpctl/bgpctl.h    3 May 2021 14:01:56 -0000       1.11
+++ usr.sbin/bgpctl/bgpctl.h    13 Jul 2021 13:20:51 -0000
@@ -24,7 +24,7 @@ struct output {
        void    (*fib_table)(struct ktable *);
        void    (*nexthop)(struct ctl_show_nexthop *);
        void    (*interface)(struct ctl_show_interface *);
-       void    (*attr)(u_char *, size_t, int);
+       void    (*attr)(u_char *, size_t, int, int);
        void    (*communities)(u_char *, size_t, struct parse_result *);
        void    (*rib)(struct ctl_show_rib *, u_char *, size_t,
                    struct parse_result *);
Index: usr.sbin/bgpctl/mrtparser.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/mrtparser.c,v
retrieving revision 1.14
diff -u -p -r1.14 mrtparser.c
--- usr.sbin/bgpctl/mrtparser.c 18 Jan 2021 12:16:09 -0000      1.14
+++ usr.sbin/bgpctl/mrtparser.c 13 Jul 2021 13:20:51 -0000
@@ -103,8 +103,10 @@ mrt_parse(int fd, struct mrt_parser *p, 
        struct mrt_bgp_state    *s;
        struct mrt_bgp_msg      *m;
        void                    *msg;
+       int                      addpath;
 
        while ((msg = mrt_read_msg(fd, &h))) {
+               addpath = 0;
                switch (ntohs(h.type)) {
                case MSG_NULL:
                case MSG_START:
@@ -163,6 +165,11 @@ mrt_parse(int fd, struct mrt_parser *p, 
                        case MRT_DUMP_V2_RIB_IPV6_UNICAST:
                        case MRT_DUMP_V2_RIB_IPV6_MULTICAST:
                        case MRT_DUMP_V2_RIB_GENERIC:
+                       case MRT_DUMP_V2_RIB_IPV4_UNICAST_ADDPATH:
+                       case MRT_DUMP_V2_RIB_IPV4_MULTICAST_ADDPATH:
+                       case MRT_DUMP_V2_RIB_IPV6_UNICAST_ADDPATH:
+                       case MRT_DUMP_V2_RIB_IPV6_MULTICAST_ADDPATH:
+                       case MRT_DUMP_V2_RIB_GENERIC_ADDPATH:
                                if (p->dump == NULL)
                                        break;
                                r = mrt_parse_v2_rib(&h, msg, verbose);
@@ -194,6 +201,10 @@ mrt_parse(int fd, struct mrt_parser *p, 
                        case BGP4MP_MESSAGE_AS4:
                        case BGP4MP_MESSAGE_LOCAL:
                        case BGP4MP_MESSAGE_AS4_LOCAL:
+                       case BGP4MP_MESSAGE_ADDPATH:
+                       case BGP4MP_MESSAGE_AS4_ADDPATH:
+                       case BGP4MP_MESSAGE_LOCAL_ADDPATH:
+                       case BGP4MP_MESSAGE_AS4_LOCAL_ADDPATH:
                                if ((m = mrt_parse_msg(&h, msg, verbose))) {
                                        if (p->message)
                                                p->message(m, p->arg);
@@ -362,10 +373,10 @@ mrt_parse_v2_rib(struct mrt_hdr *hdr, vo
        struct mrt_rib  *r;
        u_int8_t        *b = msg;
        u_int           len = ntohl(hdr->length);
-       u_int32_t       snum;
+       u_int32_t       snum, path_id = 0;
        u_int16_t       cnt, i, afi;
        u_int8_t        safi, aid;
-       int             ret;
+       int             ret, addpath = 0;
 
        if (len < sizeof(snum) + 1)
                return NULL;
@@ -381,6 +392,10 @@ mrt_parse_v2_rib(struct mrt_hdr *hdr, vo
        r->seqnum = ntohl(snum);
 
        switch (ntohs(hdr->subtype)) {
+       case MRT_DUMP_V2_RIB_IPV4_UNICAST_ADDPATH:
+       case MRT_DUMP_V2_RIB_IPV4_MULTICAST_ADDPATH:
+               r->add_path = 1;
+               /* FALLTHROUGH */
        case MRT_DUMP_V2_RIB_IPV4_UNICAST:
        case MRT_DUMP_V2_RIB_IPV4_MULTICAST:
                /* prefix */
@@ -389,6 +404,10 @@ mrt_parse_v2_rib(struct mrt_hdr *hdr, vo
                if (ret == 1)
                        goto fail;
                break;
+       case MRT_DUMP_V2_RIB_IPV6_UNICAST_ADDPATH:
+       case MRT_DUMP_V2_RIB_IPV6_MULTICAST_ADDPATH:
+               r->add_path = 1;
+               /* FALLTHROUGH */
        case MRT_DUMP_V2_RIB_IPV6_UNICAST:
        case MRT_DUMP_V2_RIB_IPV6_MULTICAST:
                /* prefix */
@@ -397,8 +416,13 @@ mrt_parse_v2_rib(struct mrt_hdr *hdr, vo
                if (ret == 1)
                        goto fail;
                break;
+       case MRT_DUMP_V2_RIB_GENERIC_ADDPATH:
+               r->add_path = 1;
+               /* FALLTHROUGH */
        case MRT_DUMP_V2_RIB_GENERIC:
                /* fetch AFI/SAFI pair */
+               if (len < 3)
+                       goto fail;
                memcpy(&afi, b, sizeof(afi));
                b += sizeof(afi);
                len -= sizeof(afi);
@@ -410,6 +434,16 @@ mrt_parse_v2_rib(struct mrt_hdr *hdr, vo
                if ((aid = mrt_afi2aid(afi, safi, verbose)) == AID_UNSPEC)
                        goto fail;
                
+               /* RFC8050 handling for add-path */
+               if (r->add_path) {
+                       if (len < sizeof(path_id))
+                               goto fail;
+                       memcpy(&path_id, b, sizeof(path_id));
+                       b += sizeof(path_id);
+                       len -= sizeof(path_id);
+                       path_id = ntohl(path_id);
+               }
+
                /* prefix */
                ret = mrt_extract_prefix(b, len, aid, &r->prefix,
                    &r->prefixlen, verbose);
@@ -453,6 +487,19 @@ mrt_parse_v2_rib(struct mrt_hdr *hdr, vo
                len -= sizeof(otm);
                entries[i].originated = ntohl(otm);
 
+               /* RFC8050 handling for add-path */
+               if (r->add_path &&
+                   ntohs(hdr->subtype) != MRT_DUMP_V2_RIB_GENERIC_ADDPATH) {
+                       if (len < sizeof(path_id) + sizeof(alen))
+                               goto fail;
+                       addpath = 0;
+                       memcpy(&path_id, b, sizeof(path_id));
+                       b += sizeof(path_id);
+                       len -= sizeof(path_id);
+                       path_id = ntohl(path_id);
+               }
+               entries[i].path_id = path_id;
+
                /* attr_len */
                memcpy(&alen, b, sizeof(alen));
                b += sizeof(alen);
@@ -1141,7 +1188,7 @@ mrt_parse_msg(struct mrt_hdr *hdr, void 
        u_int                    len = ntohl(hdr->length);
        u_int32_t                sas, das, usec;
        u_int16_t                tmp16, afi;
-       int                      r;
+       int                      r, addpath = 0;
        u_int8_t                 aid;
 
        t.tv_sec = ntohl(hdr->timestamp);
@@ -1156,7 +1203,12 @@ mrt_parse_msg(struct mrt_hdr *hdr, void 
        }
 
        switch (ntohs(hdr->subtype)) {
+       case BGP4MP_MESSAGE_ADDPATH:
+       case BGP4MP_MESSAGE_LOCAL_ADDPATH:
+               addpath = 1;
+               /* FALLTHROUGH */
        case BGP4MP_MESSAGE:
+       case BGP4MP_MESSAGE_LOCAL:
                if (len < 8)
                        return (0);
                /* source as */
@@ -1178,7 +1230,12 @@ mrt_parse_msg(struct mrt_hdr *hdr, void 
                len -= sizeof(tmp16);
                afi = ntohs(tmp16);
                break;
+       case BGP4MP_MESSAGE_AS4_ADDPATH:
+       case BGP4MP_MESSAGE_AS4_LOCAL_ADDPATH:
+               addpath = 1;
+               /* FALLTHROUGH */
        case BGP4MP_MESSAGE_AS4:
+       case BGP4MP_MESSAGE_AS4_LOCAL:
                if (len < 12)
                        return (0);
                /* source as */
@@ -1213,6 +1270,7 @@ mrt_parse_msg(struct mrt_hdr *hdr, void 
        m->time = t;
        m->src_as = sas;
        m->dst_as = das;
+       m->add_path = addpath;
 
        if ((r = mrt_extract_addr(b, len, &m->src, aid)) == -1)
                goto fail;
Index: usr.sbin/bgpctl/mrtparser.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/mrtparser.h,v
retrieving revision 1.3
diff -u -p -r1.3 mrtparser.h
--- usr.sbin/bgpctl/mrtparser.h 25 Feb 2019 11:51:58 -0000      1.3
+++ usr.sbin/bgpctl/mrtparser.h 13 Jul 2021 13:20:51 -0000
@@ -43,6 +43,7 @@ struct mrt_rib_entry {
        time_t           originated;
        u_int32_t        local_pref;
        u_int32_t        med;
+       u_int32_t        path_id;
        u_int16_t        peer_idx;
        u_int16_t        aspath_len;
        u_int16_t        nattrs;
@@ -55,6 +56,7 @@ struct mrt_rib {
        u_int32_t                seqnum;
        u_int16_t                nentries;
        u_int8_t                 prefixlen;
+       u_int8_t                 add_path;
 };
 
 /* data structures for the BGP4MP MESSAGE and STATE types */
@@ -75,6 +77,7 @@ struct mrt_bgp_msg {
        u_int32_t        src_as;
        u_int32_t        dst_as;
        u_int16_t        msg_len;
+       u_int8_t         add_path;
        void            *msg;
 };
 
Index: usr.sbin/bgpctl/output.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/output.c,v
retrieving revision 1.17
diff -u -p -r1.17 output.c
--- usr.sbin/bgpctl/output.c    27 May 2021 08:29:07 -0000      1.17
+++ usr.sbin/bgpctl/output.c    13 Jul 2021 13:20:51 -0000
@@ -666,13 +666,13 @@ show_ext_community(u_char *data, u_int16
 }
 
 static void
-show_attr(u_char *data, size_t len, int reqflags)
+show_attr(u_char *data, size_t len, int reqflags, int addpath)
 {
        u_char          *path;
        struct in_addr   id;
        struct bgpd_addr prefix;
        char            *aspath;
-       u_int32_t        as;
+       u_int32_t        as, pathid;
        u_int16_t        alen, ioff, short_as, afi;
        u_int8_t         flags, type, safi, aid, prefixlen;
        int              i, pos, e2, e4;
@@ -851,6 +851,16 @@ show_attr(u_char *data, size_t len, int 
                }
 
                while (alen > 0) {
+                       if (addpath) {
+                               if (alen <= sizeof(pathid)) {
+                                       printf("bad nlri prefix");
+                                       return;
+                               }
+                               memcpy(&pathid, data, sizeof(pathid));
+                               pathid = ntohl(pathid);
+                               data += sizeof(pathid);
+                               alen -= sizeof(pathid);
+                       }
                        switch (aid) {
                        case AID_INET6:
                                pos = nlri_get_prefix6(data, alen, &prefix,
@@ -873,6 +883,8 @@ show_attr(u_char *data, size_t len, int 
                                break;
                        }
                        printf(" %s/%u", log_addr(&prefix), prefixlen);
+                       if (addpath)
+                               printf(" path-id %u", pathid);
                        data += pos;
                        alen -= pos;
                }
@@ -940,7 +952,10 @@ show_rib_detail(struct ctl_show_rib *r, 
        printf("(via %s) Neighbor %s (", log_addr(&r->true_nexthop), s);
        free(s);
        id.s_addr = htonl(r->remote_id);
-       printf("%s)%c", inet_ntoa(id), EOL0(flag0));
+
+       if (r->flags & F_PREF_PATH_ID)
+               printf("%s) Path-Id: %u%c", inet_ntoa(id), r->path_id,
+                   EOL0(flag0));
 
        printf("    Origin %s, metric %u, localpref %u, weight %u, ovs %s, ",
            fmt_origin(r->origin, 0), r->med, r->local_pref, r->weight,
Index: usr.sbin/bgpctl/output_json.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/output_json.c,v
retrieving revision 1.11
diff -u -p -r1.11 output_json.c
--- usr.sbin/bgpctl/output_json.c       27 May 2021 08:29:07 -0000      1.11
+++ usr.sbin/bgpctl/output_json.c       13 Jul 2021 13:20:51 -0000
@@ -586,13 +586,13 @@ json_do_ext_community(u_char *data, uint
 }
 
 static void
-json_attr(u_char *data, size_t len, int reqflags)
+json_attr(u_char *data, size_t len, int reqflags, int addpath)
 {
        struct bgpd_addr prefix;
        struct in_addr id;
        char *aspath;
        u_char *path;
-       uint32_t as;
+       uint32_t as, pathid;
        uint16_t alen, afi, off, short_as;
        uint8_t flags, type, safi, aid, prefixlen;
        int e4, e2, pos;
@@ -783,6 +783,17 @@ bad_len:
 
                json_do_array("NLRI");
                while (alen > 0) {
+                       json_do_object("prefix");
+                       if (addpath) {
+                               if (alen <= sizeof(pathid)) {
+                                       json_do_printf("error", "bad path-id");
+                                       break;
+                               }
+                               memcpy(&pathid, data, sizeof(pathid));
+                               pathid = ntohl(pathid);
+                               data += sizeof(pathid);
+                               alen -= sizeof(pathid);
+                       }
                        switch (aid) {
                        case AID_INET6:
                                pos = nlri_get_prefix6(data, alen, &prefix,
@@ -808,9 +819,13 @@ bad_len:
                        }
                        json_do_printf("prefix", "%s/%u", log_addr(&prefix),
                            prefixlen);
+                       if (addpath)
+                                json_do_uint("path_id", pathid);
                        data += pos;
                        alen -= pos;
+                       json_do_end();
                }
+               json_do_end();
                break;
        case ATTR_EXT_COMMUNITIES:
                json_do_ext_community(data, alen);
@@ -854,6 +869,9 @@ json_rib(struct ctl_show_rib *r, u_char 
        id.s_addr = htonl(r->remote_id);
        json_do_printf("bgp_id", "%s", inet_ntoa(id));
        json_do_end();
+
+       if (r->flags & F_PREF_PATH_ID)
+               json_do_uint("path_id", r->path_id);
 
        /* flags */
        json_do_bool("valid", r->flags & F_PREF_ELIGIBLE);
Index: usr.sbin/bgpd/bgpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v
retrieving revision 1.415
diff -u -p -r1.415 bgpd.h
--- usr.sbin/bgpd/bgpd.h        17 Jun 2021 16:05:26 -0000      1.415
+++ usr.sbin/bgpd/bgpd.h        13 Jul 2021 13:20:51 -0000
@@ -791,6 +791,7 @@ struct ctl_neighbor {
 #define        F_PREF_ANNOUNCE 0x08
 #define        F_PREF_STALE    0x10
 #define        F_PREF_INVALID  0x20
+#define        F_PREF_PATH_ID  0x40
 
 struct ctl_show_rib {
        struct bgpd_addr        true_nexthop;
@@ -800,6 +801,7 @@ struct ctl_show_rib {
        char                    descr[PEER_DESCR_LEN];
        time_t                  age;
        u_int32_t               remote_id;
+       u_int32_t               path_id;
        u_int32_t               local_pref;
        u_int32_t               med;
        u_int32_t               weight;
Index: usr.sbin/bgpd/mrt.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/mrt.h,v
retrieving revision 1.35
diff -u -p -r1.35 mrt.h
--- usr.sbin/bgpd/mrt.h 31 Dec 2019 15:09:40 -0000      1.35
+++ usr.sbin/bgpd/mrt.h 13 Jul 2021 13:20:51 -0000
@@ -84,7 +84,11 @@ enum MRT_BGP4MP_SUBTYPES {
        BGP4MP_MESSAGE_AS4,     /* same as BGP4MP_MESSAGE with 4byte AS */
        BGP4MP_STATE_CHANGE_AS4,
        BGP4MP_MESSAGE_LOCAL,     /* same as BGP4MP_MESSAGE but for self */
-       BGP4MP_MESSAGE_AS4_LOCAL  /* originated updates. Not implemented */
+       BGP4MP_MESSAGE_AS4_LOCAL, /* originated updates. Not implemented */
+       BGP4MP_MESSAGE_ADDPATH,   /* same as above but for add-path peers */
+       BGP4MP_MESSAGE_AS4_ADDPATH,
+       BGP4MP_MESSAGE_LOCAL_ADDPATH,
+       BGP4MP_MESSAGE_AS4_LOCAL_ADDPATH,
 };
 
 /* size of the BGP4MP headers without payload */
@@ -178,7 +182,12 @@ enum MRT_DUMP_V2_SUBTYPES {
        MRT_DUMP_V2_RIB_IPV4_MULTICAST=3,
        MRT_DUMP_V2_RIB_IPV6_UNICAST=4,
        MRT_DUMP_V2_RIB_IPV6_MULTICAST=5,
-       MRT_DUMP_V2_RIB_GENERIC=6
+       MRT_DUMP_V2_RIB_GENERIC=6,
+       MRT_DUMP_V2_RIB_IPV4_UNICAST_ADDPATH=8,
+       MRT_DUMP_V2_RIB_IPV4_MULTICAST_ADDPATH=9,
+       MRT_DUMP_V2_RIB_IPV6_UNICAST_ADDPATH=10,
+       MRT_DUMP_V2_RIB_IPV6_MULTICAST_ADDPATH=11,
+       MRT_DUMP_V2_RIB_GENERIC_ADDPATH=12,
 };
 
 /*
@@ -228,7 +237,7 @@ enum MRT_DUMP_V2_SUBTYPES {
  * |     #entry      | rib entries (variable)
  * +--------+--------+--------+--------+
  *
- * The RIB_GENERIC subtype is needed for the less common AFI/SAFI pairs
+ * The RIB_GENERIC subtype is needed for the less common AFI/SAFI pairs.
  *
  * +--------+--------+--------+--------+
  * |              seq_num              |
@@ -249,6 +258,8 @@ enum MRT_DUMP_V2_SUBTYPES {
  * +--------+--------+--------+--------+
  * |          originated_time          |
  * +--------+--------+--------+--------+
+ * [    path_id in _ADDPATH variants   ]
+ * +--------+--------+--------+--------+
  * |    attr_len     |   bgp_attrs
  * +--------+--------+--------+--------+
  *      bgp_attrs (variable) ...
@@ -257,6 +268,10 @@ enum MRT_DUMP_V2_SUBTYPES {
  * Some BGP path attributes need special encoding:
  *  - the AS_PATH attribute MUST be encoded as 4-Byte AS
  *  - the MP_REACH_NLRI only consists of the nexthop len and nexthop address
+ *
+ * The non generic ADDPATH variants add the path-identifier between
+ * originated_time and attr_len. For RIB_GENERIC_ADDPATH the path_id should
+ * be part of the NLRI.
  */
 
 /*

Reply via email to