It is quite common to want to do a cross-protocol readvertisement from
IGP->EGP.  We can add rtlabels in bgpd and ospfd, but only advertise
in ospfd.

This diff lets bgpd announce routes based on rtlabels.  The existing
"cannot announce routes that point to localhost" and "cannot announce
defaults" still apply.  Should they?

OK?


Index: bgpd.conf.5
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/bgpd.conf.5,v
retrieving revision 1.146
diff -u -p -u -p -r1.146 bgpd.conf.5
--- bgpd.conf.5 17 Aug 2016 08:14:40 -0000      1.146
+++ bgpd.conf.5 14 Sep 2016 14:21:52 -0000
@@ -268,6 +268,10 @@ Log received and sent updates.
 .Pq Ic inet Ns | Ns Ic inet6
 .Ic connected Op Ic set ...\&
 .Xc
+.It Xo
+.Ic network
+.Ic rtlabel Ar label Op Ic set ...\&
+.Xc
 Announce the specified network as belonging to our AS.
 If set to
 .Ic connected ,
@@ -275,6 +279,11 @@ routes to directly attached networks wil
 If set to
 .Ic static ,
 all static routes will be announced.
+If set to
+.Ic rtlabel ,
+routes with the specified
+.Ar label
+will be announced.
 .Bd -literal -offset indent
 network 192.168.7.0/24
 .Ed
Index: bgpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v
retrieving revision 1.295
diff -u -p -u -p -r1.295 bgpd.h
--- bgpd.h      2 Sep 2016 14:00:29 -0000       1.295
+++ bgpd.h      14 Sep 2016 14:21:52 -0000
@@ -85,6 +85,7 @@
 #define        F_CTL_ADJ_IN            0x2000
 #define        F_CTL_ADJ_OUT           0x4000
 #define        F_CTL_ACTIVE            0x8000
+#define        F_RTLABEL               0x10000
 
 /*
  * Limit the number of control messages generated by the RDE and queued in
@@ -334,6 +335,7 @@ enum network_type {
        NETWORK_DEFAULT,
        NETWORK_STATIC,
        NETWORK_CONNECTED,
+       NETWORK_RTLABEL,
        NETWORK_MRTCLONE
 };
 
@@ -342,6 +344,7 @@ struct network_config {
        struct filter_set_head   attrset;
        struct rde_aspath       *asp;
        u_int                    rtableid;
+       u_int16_t                rtlabel;
        enum network_type        type;
        u_int8_t                 prefixlen;
        u_int8_t                 old;   /* used for reloading */
@@ -507,6 +510,7 @@ struct kroute_full {
        struct bgpd_addr        prefix;
        struct bgpd_addr        nexthop;
        char                    label[RTLABEL_LEN];
+       u_int16_t               labelid;
        u_int16_t               flags;
        u_short                 ifindex;
        u_int8_t                prefixlen;
Index: kroute.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/kroute.c,v
retrieving revision 1.209
diff -u -p -u -p -r1.209 kroute.c
--- kroute.c    8 Apr 2016 12:27:05 -0000       1.209
+++ kroute.c    14 Sep 2016 14:21:52 -0000
@@ -1111,6 +1111,10 @@ kr_net_match(struct ktable *kt, struct k
                        if (kr->flags & F_CONNECTED)
                                return (xn);
                        break;
+               case NETWORK_RTLABEL:
+                       if (kr->labelid == xn->net.rtlabel)
+                               return (xn);
+                       break;
                case NETWORK_MRTCLONE:
                        /* can not happen */
                        break;
@@ -1143,6 +1147,10 @@ kr_net_match6(struct ktable *kt, struct 
                        if (kr6->flags & F_CONNECTED)
                                return (xn);
                        break;
+               case NETWORK_RTLABEL:
+                       if (kr6->labelid == xn->net.rtlabel)
+                               return (xn);
+                       break;
                case NETWORK_MRTCLONE:
                        /* can not happen */
                        break;
@@ -1269,6 +1277,7 @@ sendit:
        net.prefix.aid = AID_INET;
        net.prefix.v4.s_addr = kr->prefix.s_addr;
        net.prefixlen = kr->prefixlen;
+       net.rtlabel = kr->labelid;
        net.rtableid = kt->rtableid;
 
        return (send_network(type, &net, match ? &match->net.attrset : NULL));
@@ -1337,6 +1346,7 @@ sendit:
        net.prefix.aid = AID_INET6;
        memcpy(&net.prefix.v6, &kr6->prefix, sizeof(struct in6_addr));
        net.prefixlen = kr6->prefixlen;
+       net.rtlabel = kr6->labelid;
        net.rtableid = kt->rtableid;
 
        return (send_network(type, &net, match ? &match->net.attrset : NULL));
@@ -1392,6 +1402,7 @@ kr_tofull(struct kroute *kr)
        kf.nexthop.aid = AID_INET;
        kf.nexthop.v4.s_addr = kr->nexthop.s_addr;
        strlcpy(kf.label, rtlabel_id2name(kr->labelid), sizeof(kf.label));
+       kf.labelid = kr->labelid;
        kf.flags = kr->flags;
        kf.ifindex = kr->ifindex;
        kf.prefixlen = kr->prefixlen;
@@ -1412,6 +1423,7 @@ kr6_tofull(struct kroute6 *kr6)
        kf.nexthop.aid = AID_INET6;
        memcpy(&kf.nexthop.v6, &kr6->nexthop, sizeof(struct in6_addr));
        strlcpy(kf.label, rtlabel_id2name(kr6->labelid), sizeof(kf.label));
+       kf.labelid = kr6->labelid;
        kf.flags = kr6->flags;
        kf.ifindex = kr6->ifindex;
        kf.prefixlen = kr6->prefixlen;
@@ -2780,6 +2792,7 @@ fetchtable(struct ktable *kt, u_int8_t f
        struct sockaddr         *sa, *gw, *rti_info[RTAX_MAX];
        struct sockaddr_in      *sa_in;
        struct sockaddr_in6     *sa_in6;
+       struct sockaddr_rtlabel *label;
        struct kroute_node      *kr = NULL;
        struct kroute6_node     *kr6 = NULL;
 
@@ -2858,6 +2871,14 @@ fetchtable(struct ktable *kt, u_int8_t f
                        else
                                kr->r.prefixlen =
                                    prefixlen_classful(kr->r.prefix.s_addr);
+                       rtlabel_unref(kr->r.labelid);
+                       kr->r.labelid = 0;
+                       if ((label = (struct sockaddr_rtlabel *)
+                           rti_info[RTAX_LABEL]) != NULL) {
+                               kr->r.flags |= F_RTLABEL;
+                               kr->r.labelid =
+                                   rtlabel_name2id(label->sr_label);
+                       }
                        break;
                case AF_INET6:
                        if ((kr6 = calloc(1, sizeof(struct kroute6_node))) ==
@@ -2891,6 +2912,14 @@ fetchtable(struct ktable *kt, u_int8_t f
                                kr6->r.prefixlen = 128;
                        else
                                fatalx("INET6 route without netmask");
+                       rtlabel_unref(kr6->r.labelid);
+                       kr6->r.labelid = 0;
+                       if ((label = (struct sockaddr_rtlabel *)
+                           rti_info[RTAX_LABEL]) != NULL) {
+                               kr6->r.flags |= F_RTLABEL;
+                               kr6->r.labelid =
+                                   rtlabel_name2id(label->sr_label);
+                       }
                        break;
                default:
                        continue;
Index: parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/parse.y,v
retrieving revision 1.288
diff -u -p -u -p -r1.288 parse.y
--- parse.y     21 Jun 2016 21:35:24 -0000      1.288
+++ parse.y     14 Sep 2016 14:21:52 -0000
@@ -674,6 +674,25 @@ network            : NETWORK prefix filter_set     {
 
                        TAILQ_INSERT_TAIL(netconf, n, entry);
                }
+               | NETWORK family RTLABEL STRING filter_set      {
+                       struct network  *n;
+
+                       if ((n = calloc(1, sizeof(struct network))) == NULL)
+                               fatal("new_network");
+                       if (afi2aid($2, SAFI_UNICAST, &n->net.prefix.aid) ==
+                           -1) {
+                               yyerror("unknown family");
+                               filterset_free($5);
+                               free($5);
+                               YYERROR;
+                       }
+                       n->net.type = NETWORK_RTLABEL;
+                       n->net.rtlabel = rtlabel_name2id($4);
+                       filterset_move($5, &n->net.attrset);
+                       free($5);
+
+                       TAILQ_INSERT_TAIL(netconf, n, entry);
+               }
                | NETWORK family nettype filter_set     {
                        struct network  *n;
 
Index: printconf.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/printconf.c,v
retrieving revision 1.97
diff -u -p -u -p -r1.97 printconf.c
--- printconf.c 13 Jul 2016 20:07:38 -0000      1.97
+++ printconf.c 14 Sep 2016 14:21:52 -0000
@@ -336,6 +336,10 @@ print_network(struct network_config *n, 
        case NETWORK_CONNECTED:
                printf("%snetwork %s connected", c, print_af(n->prefix.aid));
                break;
+       case NETWORK_RTLABEL:
+               printf("%snetwork %s rtlabel \"%s\"", c,
+                   print_af(n->prefix.aid), rtlabel_id2name(n->rtlabel));
+               break;
        default:
                printf("%snetwork %s/%u", c, log_addr(&n->prefix),
                    n->prefixlen);



-- 
In 1915 pancake make-up was invented but most people still preferred
syrup.

Reply via email to