]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_routemap.c
bgpd: Strip `delete` keyword when looking up for lcommunities
[mirror_frr.git] / bgpd / bgp_routemap.c
index 4953032f97bcd4dec6d0d04037907b2027e6a702..2e274124905042f1ccbcaf2c47d88453341c08a5 100644 (file)
 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
 #endif
 
+#ifndef VTYSH_EXTRACT_PL
+#include "bgpd/bgp_routemap_clippy.c"
+#endif
+
 /* Memo of route-map commands.
 
 o Cisco route-map
@@ -193,8 +197,6 @@ static void *route_value_compile(const char *arg)
        }
 
        rv = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_value));
-       if (!rv)
-               return NULL;
 
        rv->action = action;
        rv->variable = var;
@@ -320,8 +322,7 @@ static void route_match_peer_free(void *rule)
 {
        struct bgp_match_peer_compiled *pc = rule;
 
-       if (pc->interface)
-               XFREE(MTYPE_ROUTE_MAP_COMPILED, pc->interface);
+       XFREE(MTYPE_ROUTE_MAP_COMPILED, pc->interface);
 
        XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
 }
@@ -833,8 +834,6 @@ static void *route_match_vni_compile(const char *arg)
        char *end = NULL;
 
        vni = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(vni_t));
-       if (!vni)
-               return NULL;
 
        *vni = strtoul(arg, &end, 10);
        if (*end != '\0') {
@@ -905,6 +904,53 @@ struct route_map_rule_cmd route_match_evpn_route_type_cmd = {
        "evpn route-type", route_match_evpn_route_type,
        route_match_evpn_route_type_compile, route_match_evpn_route_type_free};
 
+/* Route map commands for VRF route leak with source vrf matching */
+static route_map_result_t
+route_match_vrl_source_vrf(void *rule, const struct prefix *prefix,
+                          route_map_object_t type, void *object)
+{
+       struct bgp_path_info *path;
+       char *vrf_name;
+
+       if (type == RMAP_BGP) {
+               vrf_name = rule;
+               path = (struct bgp_path_info *)object;
+
+               if (strncmp(vrf_name, "n/a", VRF_NAMSIZ) == 0)
+                       return RMAP_NOMATCH;
+
+               if (path->extra == NULL)
+                       return RMAP_NOMATCH;
+
+               if (strncmp(vrf_name, vrf_id_to_name(
+                               path->extra->bgp_orig->vrf_id), VRF_NAMSIZ)
+                   == 0)
+                       return RMAP_MATCH;
+       }
+
+       return RMAP_NOMATCH;
+}
+
+static void *route_match_vrl_source_vrf_compile(const char *arg)
+{
+       uint8_t *vrf_name = NULL;
+
+       vrf_name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+
+       return vrf_name;
+}
+
+/* Free route map's compiled `route-type' value. */
+static void route_match_vrl_source_vrf_free(void *rule)
+{
+       XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd route_match_vrl_source_vrf_cmd = {
+       "source-vrf", route_match_vrl_source_vrf,
+       route_match_vrl_source_vrf_compile,
+       route_match_vrl_source_vrf_free};
+
 /* `match local-preference LOCAL-PREF' */
 
 /* Match function return 1 if match is success else return zero. */
@@ -947,9 +993,6 @@ static void *route_match_local_pref_compile(const char *arg)
 
        local_pref = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
 
-       if (!local_pref)
-               return local_pref;
-
        *local_pref = tmpval;
        return local_pref;
 }
@@ -1504,8 +1547,7 @@ static void route_set_ip_nexthop_free(void *rule)
 {
        struct rmap_ip_nexthop_set *rins = rule;
 
-       if (rins->address)
-               XFREE(MTYPE_ROUTE_MAP_COMPILED, rins->address);
+       XFREE(MTYPE_ROUTE_MAP_COMPILED, rins->address);
 
        XFREE(MTYPE_ROUTE_MAP_COMPILED, rins);
 }
@@ -1995,22 +2037,19 @@ static route_map_result_t route_set_lcommunity_delete(void *rule,
 static void *route_set_lcommunity_delete_compile(const char *arg)
 {
        struct rmap_community *rcom;
-       char *p;
-       char *str;
-       int len;
+       char **splits;
+       int num;
+
+       frrstr_split(arg, " ", &splits, &num);
 
        rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
+       rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, splits[0]);
+       rcom->name_hash = bgp_clist_hash_key(rcom->name);
 
-       p = strchr(arg, ' ');
-       if (p) {
-               len = p - arg;
-               str = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
-               memcpy(str, arg, len);
-       } else
-               str = NULL;
+       for (int i = 0; i < num; i++)
+               XFREE(MTYPE_TMP, splits[i]);
+       XFREE(MTYPE_TMP, splits);
 
-       rcom->name = str;
-       rcom->name_hash = bgp_clist_hash_key(rcom->name);
        return rcom;
 }
 
@@ -2090,22 +2129,12 @@ static route_map_result_t route_set_community_delete(
 static void *route_set_community_delete_compile(const char *arg)
 {
        struct rmap_community *rcom;
-       char *p;
-       char *str;
-       int len;
 
        rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
 
-       p = strchr(arg, ' ');
-       if (p) {
-               len = p - arg;
-               str = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
-               memcpy(str, arg, len);
-       } else
-               str = NULL;
-
-       rcom->name = str;
+       rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
        rcom->name_hash = bgp_clist_hash_key(rcom->name);
+
        return rcom;
 }
 
@@ -2663,11 +2692,11 @@ route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix,
                    && peer->su_remote
                    && sockunion_family(peer->su_remote) == AF_INET6) {
                        /* Set next hop preference to global */
-                       path->attr->mp_nexthop_prefer_global = TRUE;
+                       path->attr->mp_nexthop_prefer_global = true;
                        SET_FLAG(path->attr->rmap_change_flags,
                                 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
                } else {
-                       path->attr->mp_nexthop_prefer_global = FALSE;
+                       path->attr->mp_nexthop_prefer_global = false;
                        SET_FLAG(path->attr->rmap_change_flags,
                                 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
                }
@@ -3054,10 +3083,8 @@ static int bgp_route_match_delete(struct vty *vty, const char *command,
                break;
        }
 
-       if (dep_name)
-               XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
-       if (rmap_name)
-               XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
+       XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
+       XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
 
        return retval;
 }
@@ -3250,6 +3277,15 @@ static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
                if (bgp->table_map[afi][safi].name
                    && (strcmp(rmap_name, bgp->table_map[afi][safi].name)
                        == 0)) {
+
+                       /* bgp->table_map[afi][safi].map  is NULL.
+                        * i.e Route map creation event.
+                        * So update applied_counter.
+                        * If it is not NULL, i.e It may be routemap updation or
+                        * deletion. so no need to update the counter.
+                        */
+                       if (!bgp->table_map[afi][safi].map)
+                               route_map_counter_increment(map);
                        bgp->table_map[afi][safi].map = map;
 
                        if (BGP_DEBUG(zebra, ZEBRA))
@@ -3272,6 +3308,9 @@ static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
                            || (strcmp(rmap_name, bgp_static->rmap.name) != 0))
                                continue;
 
+                       if (!bgp_static->rmap.map)
+                               route_map_counter_increment(map);
+
                        bgp_static->rmap.map = map;
 
                        if (route_update && !bgp_static->backdoor) {
@@ -3303,6 +3342,9 @@ static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
                                    || (strcmp(rmap_name, red->rmap.name) != 0))
                                        continue;
 
+                               if (!red->rmap.map)
+                                       route_map_counter_increment(map);
+
                                red->rmap.map = map;
 
                                if (!route_update)
@@ -3333,7 +3375,7 @@ static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
                                "Processing route_map %s update on advertise type5 route command",
                                rmap_name);
 
-               if (route_update) {
+               if (route_update && advertise_type5_routes(bgp, afi)) {
                        bgp_evpn_withdraw_type5_routes(bgp, afi, safi);
                        bgp_evpn_advertise_type5_routes(bgp, afi, safi);
                }
@@ -3523,6 +3565,29 @@ DEFUN (no_match_evpn_default_route,
                                      RMAP_EVENT_MATCH_DELETED);
 }
 
+DEFPY(match_vrl_source_vrf,
+      match_vrl_source_vrf_cmd,
+      "match source-vrf NAME$vrf_name",
+      MATCH_STR
+      "source vrf\n"
+      "The VRF name\n")
+{
+       return bgp_route_match_add(vty, "source-vrf", vrf_name,
+                                  RMAP_EVENT_MATCH_ADDED);
+}
+
+DEFPY(no_match_vrl_source_vrf,
+      no_match_vrl_source_vrf_cmd,
+      "no match source-vrf NAME$vrf_name",
+      NO_STR
+      MATCH_STR
+      "source vrf\n"
+      "The VRF name\n")
+{
+       return bgp_route_match_delete(vty, "source-vrf", vrf_name,
+                                     RMAP_EVENT_MATCH_DELETED);
+}
+
 DEFUN (match_peer,
        match_peer_cmd,
        "match peer <A.B.C.D|X:X::X:X|WORD>",
@@ -4262,17 +4327,13 @@ DEFUN (set_community_delete,
        "Delete matching communities\n")
 {
        int idx_comm_list = 2;
-       char *str;
-
-       str = XCALLOC(MTYPE_TMP,
-                     strlen(argv[idx_comm_list]->arg) + strlen(" delete") + 1);
-       strcpy(str, argv[idx_comm_list]->arg);
-       strcpy(str + strlen(argv[idx_comm_list]->arg), " delete");
+       char *args;
 
+       args = argv_concat(argv, argc, idx_comm_list);
        generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), "comm-list",
-                       str);
+                       args);
+       XFREE(MTYPE_TMP, args);
 
-       XFREE(MTYPE_TMP, str);
        return CMD_SUCCESS;
 }
 
@@ -4361,16 +4422,14 @@ DEFUN (set_lcommunity_delete,
        "Large Community-list name\n"
        "Delete matching large communities\n")
 {
-       char *str;
-
-       str = XCALLOC(MTYPE_TMP, strlen(argv[2]->arg) + strlen(" delete") + 1);
-       strcpy(str, argv[2]->arg);
-       strcpy(str + strlen(argv[2]->arg), " delete");
+       int idx_lcomm_list = 2;
+       char *args;
 
+       args = argv_concat(argv, argc, idx_lcomm_list);
        generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
-                       "large-comm-list", str);
+                       "large-comm-list", args);
+       XFREE(MTYPE_TMP, args);
 
-       XFREE(MTYPE_TMP, str);
        return CMD_SUCCESS;
 }
 
@@ -4977,6 +5036,7 @@ void bgp_route_map_init(void)
        route_map_install_match(&route_match_evpn_vni_cmd);
        route_map_install_match(&route_match_evpn_route_type_cmd);
        route_map_install_match(&route_match_evpn_default_route_cmd);
+       route_map_install_match(&route_match_vrl_source_vrf_cmd);
 
        route_map_install_set(&route_set_ip_nexthop_cmd);
        route_map_install_set(&route_set_local_pref_cmd);
@@ -5015,6 +5075,8 @@ void bgp_route_map_init(void)
        install_element(RMAP_NODE, &no_match_evpn_route_type_cmd);
        install_element(RMAP_NODE, &match_evpn_default_route_cmd);
        install_element(RMAP_NODE, &no_match_evpn_default_route_cmd);
+       install_element(RMAP_NODE, &match_vrl_source_vrf_cmd);
+       install_element(RMAP_NODE, &no_match_vrl_source_vrf_cmd);
 
        install_element(RMAP_NODE, &match_aspath_cmd);
        install_element(RMAP_NODE, &no_match_aspath_cmd);