]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: handle FS redirect IP rule in PBR
authorPhilippe Guibert <philippe.guibert@6wind.com>
Wed, 28 Mar 2018 12:51:57 +0000 (14:51 +0200)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Thu, 3 May 2018 13:15:08 +0000 (15:15 +0200)
If a new rule is identified, a new table identifier is created.
In that table, add a default route when possible. If redirect IP rule is
identified, then add a default route to that IP address.
If redirect VRF is identified, nothing is done for now

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
bgpd/bgp_pbr.c
bgpd/bgp_zebra.c
bgpd/bgp_zebra.h

index 83710f046d1e2c5db64925ce43806e57e7c86337..d7a4c920f462bdadacb386c95b9bb841892b53a3 100644 (file)
@@ -886,8 +886,11 @@ static void bgp_pbr_policyroute_add_to_zebra(struct bgp *bgp,
         * it will be suppressed subsequently
         */
        /* ip rule add */
-       if (!bpa->installed)
+       if (!bpa->installed) {
                bgp_send_pbr_rule_action(bpa, true);
+               bgp_zebra_announce_default(bgp, nh,
+                                          AFI_IP, bpa->table_id, true);
+       }
 
        /* ipset create */
        if (bpm && !bpm->installed)
index 2c1ccfd932af9776c1d6ed9899cc1b9acf628b05..6482ee8fed453f10fa1179360b4e92c900094d42 100644 (file)
@@ -1464,6 +1464,7 @@ void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info,
                        struct bgp *bgp, safi_t safi)
 {
        struct zapi_route api;
+       struct peer *peer;
 
        /* Don't try to install if we're not connected to Zebra or Zebra doesn't
         * know of this instance.
@@ -1471,9 +1472,11 @@ void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info,
        if (!bgp_install_info_to_zebra(bgp))
                return;
 
-       if (safi == SAFI_FLOWSPEC)
+       if (safi == SAFI_FLOWSPEC) {
+               peer = info->peer;
                return bgp_pbr_update_entry(peer->bgp, p,
                                            info, AFI_IP, safi, false);
+       }
 
        memset(&api, 0, sizeof(api));
        memcpy(&api.rmac, &(info->attr->rmac), sizeof(struct ethaddr));
@@ -2559,3 +2562,62 @@ void bgp_send_pbr_iptable(struct bgp_pbr_action *pba,
        if (!zclient_send_message(zclient) && install)
                pbm->install_iptable_in_progress = true;
 }
+
+/* inject in table <table_id> a default route to:
+ * - if nexthop IP is present : to this nexthop
+ * - if vrf is different from local : to the matching VRF
+ */
+void bgp_zebra_announce_default(struct bgp *bgp, struct nexthop *nh,
+                               afi_t afi, uint32_t table_id, bool announce)
+{
+       struct zapi_nexthop *api_nh;
+       struct zapi_route api;
+       struct prefix p;
+
+       if (!nh || nh->type != NEXTHOP_TYPE_IPV4
+           || nh->vrf_id == VRF_UNKNOWN)
+               return;
+       memset(&p, 0, sizeof(struct prefix));
+       /* default route */
+       if (afi != AFI_IP)
+               return;
+       p.family = AF_INET;
+       memset(&api, 0, sizeof(api));
+       api.vrf_id = bgp->vrf_id;
+       api.type = ZEBRA_ROUTE_BGP;
+       api.safi = SAFI_UNICAST;
+       api.prefix = p;
+       api.tableid = table_id;
+       api.nexthop_num = 1;
+       SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID);
+       SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
+       api_nh = &api.nexthops[0];
+
+       /* redirect IP */
+       if (nh->gate.ipv4.s_addr) {
+               char buff[PREFIX_STRLEN];
+
+               api_nh->vrf_id = nh->vrf_id;
+               api_nh->gate.ipv4 = nh->gate.ipv4;
+               api_nh->type = NEXTHOP_TYPE_IPV4;
+
+               inet_ntop(AF_INET, &(nh->gate.ipv4), buff, INET_ADDRSTRLEN);
+               if (BGP_DEBUG(zebra, ZEBRA))
+                       zlog_info("BGP: sending default route to %s table %d (redirect IP)",
+                                 buff, table_id);
+               zclient_route_send(announce ? ZEBRA_ROUTE_ADD
+                                  : ZEBRA_ROUTE_DELETE,
+                                  zclient, &api);
+       } else if (nh->vrf_id != bgp->vrf_id) {
+               struct vrf *vrf;
+               vrf = vrf_lookup_by_id(nh->vrf_id);
+
+               if (!vrf)
+                       return;
+               /* find default route for vrf
+                * BGP may not have default route distributed in
+                * its context. This use case is not handled for now
+                */
+               return;
+       }
+}
index 003db65318bb46e02a0a4dd50e7db74292da3efe..63ecb9fc8219ecbaa67f6b100584f56d98f1f422 100644 (file)
@@ -83,4 +83,7 @@ extern void bgp_send_pbr_iptable(struct bgp_pbr_action *pba,
                          struct bgp_pbr_match *pbm,
                          bool install);
 
+extern void bgp_zebra_announce_default(struct bgp *bgp, struct nexthop *nh,
+                               afi_t afi, uint32_t table_id, bool announce);
+
 #endif /* _QUAGGA_BGP_ZEBRA_H */