]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_zebra.c
bgpd: support for flowspec tcp flags
[mirror_frr.git] / bgpd / bgp_zebra.c
index 4a909d8cdc0247b5c0bb94fcc1b0eb4c248a5f4b..d201b48bad7d77f105d4e2ff6d3885dfbae16f7c 100644 (file)
@@ -1001,6 +1001,7 @@ static bool bgp_tm_status_connected;
 static bool bgp_tm_chunk_obtained;
 #define BGP_FLOWSPEC_TABLE_CHUNK 100000
 static uint32_t bgp_tm_min, bgp_tm_max, bgp_tm_chunk_size;
+struct bgp *bgp_tm_bgp;
 
 static int bgp_zebra_tm_connect(struct thread *t)
 {
@@ -1024,8 +1025,11 @@ static int bgp_zebra_tm_connect(struct thread *t)
                if (!bgp_tm_chunk_obtained) {
                        if (bgp_zebra_get_table_range(bgp_tm_chunk_size,
                                                      &bgp_tm_min,
-                                                     &bgp_tm_max) >= 0)
+                                                     &bgp_tm_max) >= 0) {
                                bgp_tm_chunk_obtained = true;
+                               /* parse non installed entries */
+                               bgp_zebra_announce_table(bgp_tm_bgp, AFI_IP, SAFI_FLOWSPEC);
+                       }
                }
        }
        thread_add_timer(bm->master, bgp_zebra_tm_connect, zclient, delay,
@@ -1033,6 +1037,11 @@ static int bgp_zebra_tm_connect(struct thread *t)
        return 0;
 }
 
+bool bgp_zebra_tm_chunk_obtained(void)
+{
+       return bgp_tm_chunk_obtained;
+}
+
 uint32_t bgp_zebra_tm_get_id(void)
 {
        static int table_id;
@@ -1042,7 +1051,7 @@ uint32_t bgp_zebra_tm_get_id(void)
        return bgp_tm_min++;
 }
 
-void bgp_zebra_init_tm_connect(void)
+void bgp_zebra_init_tm_connect(struct bgp *bgp)
 {
        int delay = 1;
 
@@ -1054,6 +1063,7 @@ void bgp_zebra_init_tm_connect(void)
        bgp_tm_chunk_obtained = false;
        bgp_tm_min = bgp_tm_max = 0;
        bgp_tm_chunk_size = BGP_FLOWSPEC_TABLE_CHUNK;
+       bgp_tm_bgp = bgp;
        thread_add_timer(bm->master, bgp_zebra_tm_connect, zclient, delay,
                         &bgp_tm_thread_connect);
 }
@@ -1193,7 +1203,7 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
                return;
 
        if (bgp_debug_zebra(p))
-               prefix2str(&api.prefix, buf_prefix, sizeof(buf_prefix));
+               prefix2str(p, buf_prefix, sizeof(buf_prefix));
 
        if (safi == SAFI_FLOWSPEC)
                return bgp_pbr_update_entry(bgp, &rn->p,
@@ -1225,13 +1235,6 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
 
        tag = info->attr->tag;
 
-       /*
-        * When we create an aggregate route we must also install a
-        * Null0 route in the RIB
-        */
-       if (info->sub_type == BGP_ROUTE_AGGREGATE)
-               zapi_route_set_blackhole(&api, BLACKHOLE_NULL);
-
        /* If the route's source is EVPN, flag as such. */
        is_evpn = is_route_parent_evpn(info);
        if (is_evpn)
@@ -1313,7 +1316,7 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
                                        &mpinfo_cp->attr->nexthop,
                                        mpinfo_cp->attr, is_evpn, api_nh);
                } else {
-                       ifindex_t ifindex;
+                       ifindex_t ifindex = IFINDEX_INTERNAL;
                        struct in6_addr *nexthop;
 
                        if (bgp->table_map[afi][safi].name) {
@@ -1371,7 +1374,14 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
        if (has_valid_label && !(CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE)))
                SET_FLAG(api.message, ZAPI_MESSAGE_LABEL);
 
-       if (info->sub_type != BGP_ROUTE_AGGREGATE)
+       /*
+        * When we create an aggregate route we must also
+        * install a Null0 route in the RIB, so overwrite
+        * what was written into api with a blackhole route
+        */
+       if (info->sub_type == BGP_ROUTE_AGGREGATE)
+               zapi_route_set_blackhole(&api, BLACKHOLE_NULL);
+       else
                api.nexthop_num = valid_nh_count;
 
        SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
@@ -1962,6 +1972,7 @@ static int rule_notify_owner(int command, struct zclient *zclient,
                        zlog_debug("%s: Received RULE_INSTALLED",
                                   __PRETTY_FUNCTION__);
                break;
+       case ZAPI_RULE_FAIL_REMOVE:
        case ZAPI_RULE_REMOVED:
                if (BGP_DEBUG(zebra, ZEBRA))
                        zlog_debug("%s: Received RULE REMOVED",
@@ -1987,8 +1998,8 @@ static int ipset_notify_owner(int command, struct zclient *zclient,
        bgp_pbim = bgp_pbr_match_ipset_lookup(vrf_id, unique);
        if (!bgp_pbim) {
                if (BGP_DEBUG(zebra, ZEBRA))
-                       zlog_debug("%s: Fail to look BGP match (%u)",
-                                  __PRETTY_FUNCTION__, unique);
+                       zlog_debug("%s: Fail to look BGP match ( %u %u)",
+                                  __PRETTY_FUNCTION__, note, unique);
                return 0;
        }
 
@@ -2007,6 +2018,7 @@ static int ipset_notify_owner(int command, struct zclient *zclient,
                        zlog_debug("%s: Received IPSET_INSTALLED",
                                   __PRETTY_FUNCTION__);
                break;
+       case ZAPI_IPSET_FAIL_REMOVE:
        case ZAPI_IPSET_REMOVED:
                if (BGP_DEBUG(zebra, ZEBRA))
                        zlog_debug("%s: Received IPSET REMOVED",
@@ -2036,8 +2048,8 @@ static int ipset_entry_notify_owner(int command, struct zclient *zclient,
                                                     unique);
        if (!bgp_pbime) {
                if (BGP_DEBUG(zebra, ZEBRA))
-                       zlog_debug("%s: Fail to look BGP match entry (%u)",
-                                  __PRETTY_FUNCTION__, unique);
+                       zlog_debug("%s: Fail to look BGP match entry (%u %u)",
+                                  __PRETTY_FUNCTION__, note, unique);
                return 0;
        }
 
@@ -2050,12 +2062,22 @@ static int ipset_entry_notify_owner(int command, struct zclient *zclient,
                bgp_pbime->install_in_progress = false;
                break;
        case ZAPI_IPSET_ENTRY_INSTALLED:
-               bgp_pbime->installed = true;
-               bgp_pbime->install_in_progress = false;
-               if (BGP_DEBUG(zebra, ZEBRA))
-                       zlog_debug("%s: Received IPSET_ENTRY_INSTALLED",
-                                  __PRETTY_FUNCTION__);
+               {
+                       struct bgp_info *bgp_info;
+                       struct bgp_info_extra *extra;
+
+                       bgp_pbime->installed = true;
+                       bgp_pbime->install_in_progress = false;
+                       if (BGP_DEBUG(zebra, ZEBRA))
+                               zlog_debug("%s: Received IPSET_ENTRY_INSTALLED",
+                                          __PRETTY_FUNCTION__);
+                       /* link bgp_info to bpme */
+                       bgp_info = (struct bgp_info *)bgp_pbime->bgp_info;
+                       extra = bgp_info_extra_get(bgp_info);
+                       extra->bgp_fs_pbr = (void *)bgp_pbime;
+               }
                break;
+       case ZAPI_IPSET_ENTRY_FAIL_REMOVE:
        case ZAPI_IPSET_ENTRY_REMOVED:
                if (BGP_DEBUG(zebra, ZEBRA))
                        zlog_debug("%s: Received IPSET_ENTRY_REMOVED",
@@ -2080,8 +2102,8 @@ static int iptable_notify_owner(int command, struct zclient *zclient,
        bgpm = bgp_pbr_match_iptable_lookup(vrf_id, unique);
        if (!bgpm) {
                if (BGP_DEBUG(zebra, ZEBRA))
-                       zlog_debug("%s: Fail to look BGP iptable (%u)",
-                                  __PRETTY_FUNCTION__, unique);
+                       zlog_debug("%s: Fail to look BGP iptable (%u %u)",
+                                  __PRETTY_FUNCTION__, note, unique);
                return 0;
        }
        switch (note) {
@@ -2100,6 +2122,7 @@ static int iptable_notify_owner(int command, struct zclient *zclient,
                                   __PRETTY_FUNCTION__);
                bgpm->action->refcnt++;
                break;
+       case ZAPI_IPTABLE_FAIL_REMOVE:
        case ZAPI_IPTABLE_REMOVED:
                if (BGP_DEBUG(zebra, ZEBRA))
                        zlog_debug("%s: Received IPTABLE REMOVED",
@@ -2167,6 +2190,12 @@ static void bgp_encode_pbr_ipset_entry_match(struct stream *s,
        stream_putc(s, pbime->dst.family);
        stream_putc(s, pbime->dst.prefixlen);
        stream_put(s, &pbime->dst.u.prefix, prefix_blen(&pbime->dst));
+
+       stream_putw(s, pbime->src_port_min);
+       stream_putw(s, pbime->src_port_max);
+       stream_putw(s, pbime->dst_port_min);
+       stream_putw(s, pbime->dst_port_max);
+       stream_putc(s, pbime->proto);
 }
 
 static void bgp_encode_pbr_iptable_match(struct stream *s,
@@ -2190,6 +2219,10 @@ static void bgp_encode_pbr_iptable_match(struct stream *s,
        stream_putl(s, bpa->fwmark);
        stream_put(s, pbm->ipset_name,
                   ZEBRA_IPSET_NAME_SIZE);
+       stream_putw(s, pbm->pkt_len_min);
+       stream_putw(s, pbm->pkt_len_max);
+       stream_putw(s, pbm->tcp_flags);
+       stream_putw(s, pbm->tcp_mask_flags);
 }
 
 /* BGP has established connection with Zebra. */
@@ -2220,6 +2253,40 @@ static void bgp_zebra_connected(struct zclient *zclient)
         */
 }
 
+static int bgp_zebra_process_local_es(int cmd, struct zclient *zclient,
+                                     zebra_size_t length, vrf_id_t vrf_id)
+{
+       esi_t esi;
+       struct bgp *bgp = NULL;
+       struct stream *s = NULL;
+       char buf[ESI_STR_LEN];
+       char buf1[INET6_ADDRSTRLEN];
+       struct ipaddr originator_ip;
+
+       memset(&esi, 0, sizeof(esi_t));
+       memset(&originator_ip, 0, sizeof(struct ipaddr));
+
+       bgp = bgp_lookup_by_vrf_id(vrf_id);
+       if (!bgp)
+               return 0;
+
+       s = zclient->ibuf;
+       stream_get(&esi, s, sizeof(esi_t));
+       stream_get(&originator_ip, s, sizeof(struct ipaddr));
+
+       if (BGP_DEBUG(zebra, ZEBRA))
+               zlog_debug("Rx %s ESI %s originator-ip %s",
+                          (cmd == ZEBRA_LOCAL_ES_ADD) ? "add" : "del",
+                          esi_to_str(&esi, buf, sizeof(buf)),
+                          ipaddr2str(&originator_ip, buf1, sizeof(buf1)));
+
+       if (cmd == ZEBRA_LOCAL_ES_ADD)
+               bgp_evpn_local_es_add(bgp, &esi, &originator_ip);
+       else
+               bgp_evpn_local_es_del(bgp, &esi, &originator_ip);
+       return 0;
+}
+
 static int bgp_zebra_process_local_l3vni(int cmd, struct zclient *zclient,
                                         zebra_size_t length, vrf_id_t vrf_id)
 {
@@ -2455,6 +2522,8 @@ void bgp_zebra_init(struct thread_master *master)
        zclient->nexthop_update = bgp_read_nexthop_update;
        zclient->import_check_update = bgp_read_import_check_update;
        zclient->fec_update = bgp_read_fec_update;
+       zclient->local_es_add = bgp_zebra_process_local_es;
+       zclient->local_es_del = bgp_zebra_process_local_es;
        zclient->local_vni_add = bgp_zebra_process_local_vni;
        zclient->local_vni_del = bgp_zebra_process_local_vni;
        zclient->local_macip_add = bgp_zebra_process_local_macip;
@@ -2490,8 +2559,10 @@ void bgp_send_pbr_rule_action(struct bgp_pbr_action *pbra, bool install)
 
        if (pbra->install_in_progress)
                return;
-       zlog_debug("%s: table %d fwmark %d %d", __PRETTY_FUNCTION__,
-                  pbra->table_id, pbra->fwmark, install);
+       if (BGP_DEBUG(zebra, ZEBRA))
+               zlog_debug("%s: table %d fwmark %d %d",
+                          __PRETTY_FUNCTION__,
+                          pbra->table_id, pbra->fwmark, install);
        s = zclient->obuf;
        stream_reset(s);
 
@@ -2513,8 +2584,10 @@ void bgp_send_pbr_ipset_match(struct bgp_pbr_match *pbrim, bool install)
 
        if (pbrim->install_in_progress)
                return;
-       zlog_debug("%s: name %s type %d %d", __PRETTY_FUNCTION__,
-                  pbrim->ipset_name, pbrim->type, install);
+       if (BGP_DEBUG(zebra, ZEBRA))
+               zlog_debug("%s: name %s type %d %d",
+                          __PRETTY_FUNCTION__,
+                          pbrim->ipset_name, pbrim->type, install);
        s = zclient->obuf;
        stream_reset(s);
 
@@ -2539,9 +2612,10 @@ void bgp_send_pbr_ipset_entry_match(struct bgp_pbr_match_entry *pbrime,
 
        if (pbrime->install_in_progress)
                return;
-       zlog_debug("%s: name %s %d %d", __PRETTY_FUNCTION__,
-                  pbrime->backpointer->ipset_name,
-                  pbrime->unique, install);
+       if (BGP_DEBUG(zebra, ZEBRA))
+               zlog_debug("%s: name %s %d %d", __PRETTY_FUNCTION__,
+                          pbrime->backpointer->ipset_name,
+                          pbrime->unique, install);
        s = zclient->obuf;
        stream_reset(s);
 
@@ -2559,16 +2633,56 @@ void bgp_send_pbr_ipset_entry_match(struct bgp_pbr_match_entry *pbrime,
                pbrime->install_in_progress = true;
 }
 
+static void bgp_encode_pbr_interface_list(struct bgp *bgp, struct stream *s)
+{
+       struct bgp_pbr_config *bgp_pbr_cfg = bgp->bgp_pbr_cfg;
+       struct bgp_pbr_interface_head *head;
+       struct bgp_pbr_interface *pbr_if;
+       struct interface *ifp;
+
+       if (!bgp_pbr_cfg)
+               return;
+       head = &(bgp_pbr_cfg->ifaces_by_name_ipv4);
+
+       RB_FOREACH (pbr_if, bgp_pbr_interface_head, head) {
+               ifp = if_lookup_by_name(pbr_if->name, bgp->vrf_id);
+               if (ifp)
+                       stream_putl(s, ifp->ifindex);
+       }
+}
+
+static int bgp_pbr_get_ifnumber(struct bgp *bgp)
+{
+       struct bgp_pbr_config *bgp_pbr_cfg = bgp->bgp_pbr_cfg;
+       struct bgp_pbr_interface_head *head;
+       struct bgp_pbr_interface *pbr_if;
+       int cnt = 0;
+
+       if (!bgp_pbr_cfg)
+               return 0;
+       head = &(bgp_pbr_cfg->ifaces_by_name_ipv4);
+
+       RB_FOREACH (pbr_if, bgp_pbr_interface_head, head) {
+               if (if_lookup_by_name(pbr_if->name, bgp->vrf_id))
+                       cnt++;
+       }
+       return cnt;
+}
+
 void bgp_send_pbr_iptable(struct bgp_pbr_action *pba,
                          struct bgp_pbr_match *pbm,
                          bool install)
 {
        struct stream *s;
+       int ret = 0;
+       int nb_interface;
 
        if (pbm->install_iptable_in_progress)
                return;
-       zlog_debug("%s: name %s type %d mark %d %d", __PRETTY_FUNCTION__,
-                  pbm->ipset_name, pbm->type, pba->fwmark, install);
+       if (BGP_DEBUG(zebra, ZEBRA))
+               zlog_debug("%s: name %s type %d mark %d %d",
+                          __PRETTY_FUNCTION__, pbm->ipset_name,
+                          pbm->type, pba->fwmark, install);
        s = zclient->obuf;
        stream_reset(s);
 
@@ -2578,11 +2692,17 @@ void bgp_send_pbr_iptable(struct bgp_pbr_action *pba,
                              VRF_DEFAULT);
 
        bgp_encode_pbr_iptable_match(s, pba, pbm);
-
+       nb_interface = bgp_pbr_get_ifnumber(pba->bgp);
+       stream_putl(s, nb_interface);
+       if (nb_interface)
+               bgp_encode_pbr_interface_list(pba->bgp, s);
        stream_putw_at(s, 0, stream_get_endp(s));
-       if (!zclient_send_message(zclient) && install) {
-               pbm->install_iptable_in_progress = true;
-               pba->refcnt++;
+       ret = zclient_send_message(zclient);
+       if (install) {
+               if (ret)
+                       pba->refcnt++;
+               else
+                       pbm->install_iptable_in_progress = true;
        }
 }
 
@@ -2626,7 +2746,8 @@ void bgp_zebra_announce_default(struct bgp *bgp, struct nexthop *nh,
 
                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)",
+                       zlog_info("BGP: %s default route to %s table %d (redirect IP)",
+                                 announce ? "adding" : "withdrawing",
                                  buff, table_id);
                zclient_route_send(announce ? ZEBRA_ROUTE_ADD
                                   : ZEBRA_ROUTE_DELETE,
@@ -2648,7 +2769,8 @@ void bgp_zebra_announce_default(struct bgp *bgp, struct nexthop *nh,
                api_nh->type = NEXTHOP_TYPE_IFINDEX;
                api_nh->ifindex = ifp->ifindex;
                if (BGP_DEBUG(zebra, ZEBRA))
-                       zlog_info("BGP: sending default route to %s table %d (redirect VRF)",
+                       zlog_info("BGP: %s default route to %s table %d (redirect VRF)",
+                                 announce ? "adding" : "withdrawing",
                                  vrf->name, table_id);
                zclient_route_send(announce ? ZEBRA_ROUTE_ADD
                                   : ZEBRA_ROUTE_DELETE,