]> git.proxmox.com Git - mirror_frr.git/blobdiff - pbrd/pbr_vty.c
Merge pull request #5409 from qlyoung/bgpd-lcom-ecom-parse-fixes
[mirror_frr.git] / pbrd / pbr_vty.c
index 067d5c01fdfac621cebd1a0bf8fdc70dc88d8888..bc4aa947a9c07922566af576d3d0e9ddfff361ef 100644 (file)
@@ -25,6 +25,7 @@
 #include "vrf.h"
 #include "nexthop.h"
 #include "nexthop_group.h"
+#include "nexthop_group_private.h"
 #include "log.h"
 #include "debug.h"
 #include "pbr.h"
@@ -38,7 +39,7 @@
 #include "pbrd/pbr_vty_clippy.c"
 #endif
 
-DEFUN_NOSH(pbr_map, pbr_map_cmd, "pbr-map WORD seq (1-700)",
+DEFUN_NOSH(pbr_map, pbr_map_cmd, "pbr-map PBRMAP seq (1-700)",
           "Create pbr-map or enter pbr-map command mode\n"
           "The name of the PBR MAP\n"
           "Sequence to insert in existing pbr-map entry\n"
@@ -54,7 +55,7 @@ DEFUN_NOSH(pbr_map, pbr_map_cmd, "pbr-map WORD seq (1-700)",
        return CMD_SUCCESS;
 }
 
-DEFUN_NOSH(no_pbr_map, no_pbr_map_cmd, "no pbr-map WORD [seq (1-700)]",
+DEFUN_NOSH(no_pbr_map, no_pbr_map_cmd, "no pbr-map PBRMAP [seq (1-700)]",
           NO_STR
           "Delete pbr-map\n"
           "The name of the PBR MAP\n"
@@ -132,10 +133,8 @@ DEFPY(pbr_map_match_src, pbr_map_match_src_cmd,
                if (!pbrms->src)
                        pbrms->src = prefix_new();
                prefix_copy(pbrms->src, prefix);
-       } else {
-               prefix_free(pbrms->src);
-               pbrms->src = 0;
-       }
+       } else
+               prefix_free(&pbrms->src);
 
        pbr_map_check(pbrms);
 
@@ -161,9 +160,34 @@ DEFPY(pbr_map_match_dst, pbr_map_match_dst_cmd,
                if (!pbrms->dst)
                        pbrms->dst = prefix_new();
                prefix_copy(pbrms->dst, prefix);
+       } else
+               prefix_free(&pbrms->dst);
+
+       pbr_map_check(pbrms);
+
+       return CMD_SUCCESS;
+}
+
+DEFPY(pbr_map_match_mark, pbr_map_match_mark_cmd,
+       "[no] match mark (1-4294967295)$mark",
+       NO_STR
+       "Match the rest of the command\n"
+       "Choose the mark value to use\n"
+       "mark\n")
+{
+       struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+
+#ifndef GNU_LINUX
+       vty_out(vty, "pbr marks are not supported on this platform");
+       return CMD_WARNING_CONFIG_FAILED;
+#endif
+
+       if (!no) {
+               if (pbrms->mark == (uint32_t) mark)
+                       return CMD_SUCCESS;
+               pbrms->mark = (uint32_t) mark;
        } else {
-               prefix_free(pbrms->dst);
-               pbrms->dst = NULL;
+               pbrms->mark = 0;
        }
 
        pbr_map_check(pbrms);
@@ -171,12 +195,15 @@ DEFPY(pbr_map_match_dst, pbr_map_match_dst_cmd,
        return CMD_SUCCESS;
 }
 
+#define SET_VRF_EXISTS_STR                                                     \
+       "A `set vrf XX` command already exists, please remove that first\n"
+
 DEFPY(pbr_map_nexthop_group, pbr_map_nexthop_group_cmd,
-       "[no] set nexthop-group NAME$name",
-       NO_STR
-       "Set for the PBR-MAP\n"
-       "nexthop-group to use\n"
-       "The name of the nexthop-group\n")
+      "[no] set nexthop-group NHGNAME$name",
+      NO_STR
+      "Set for the PBR-MAP\n"
+      "nexthop-group to use\n"
+      "The name of the nexthop-group\n")
 {
        struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
        struct nexthop_group_cmd *nhgc;
@@ -187,16 +214,22 @@ DEFPY(pbr_map_nexthop_group, pbr_map_nexthop_group_cmd,
                return CMD_WARNING_CONFIG_FAILED;
        }
 
+       if (pbrms->vrf_lookup || pbrms->vrf_unchanged) {
+               vty_out(vty, SET_VRF_EXISTS_STR);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
        nhgc = nhgc_find(name);
        if (!nhgc) {
                vty_out(vty, "Specified nexthop-group %s does not exist\n",
                        name);
-               vty_out(vty, "PBR-MAP will not be applied until it is created\n");
+               vty_out(vty,
+                       "PBR-MAP will not be applied until it is created\n");
        }
 
        if (no) {
                if (pbrms->nhgrp_name && strcmp(name, pbrms->nhgrp_name) == 0)
-                       pbr_map_delete_nexthop_group(pbrms);
+                       pbr_map_delete_nexthops(pbrms);
                else {
                        vty_out(vty,
                                "Nexthop Group specified: %s does not exist to remove",
@@ -226,7 +259,7 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd,
          <A.B.C.D|X:X::X:X>$addr [INTERFACE$intf]\
          |INTERFACE$intf\
        >\
-        [nexthop-vrf NAME$name]",
+        [nexthop-vrf NAME$vrf_name]",
       NO_STR
       "Set for the PBR-MAP\n"
       "Specify one of the nexthops in this map\n"
@@ -248,13 +281,18 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd,
                return CMD_WARNING_CONFIG_FAILED;
        }
 
-       if (name)
-               vrf = vrf_lookup_by_name(name);
+       if (pbrms->vrf_lookup || pbrms->vrf_unchanged) {
+               vty_out(vty, SET_VRF_EXISTS_STR);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       if (vrf_name)
+               vrf = vrf_lookup_by_name(vrf_name);
        else
                vrf = vrf_lookup_by_id(VRF_DEFAULT);
 
        if (!vrf) {
-               vty_out(vty, "Specified: %s is non-existent\n", name);
+               vty_out(vty, "Specified: %s is non-existent\n", vrf_name);
                return CMD_WARNING_CONFIG_FAILED;
        }
 
@@ -329,13 +367,15 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd,
                nh = nexthop_new();
 
                memcpy(nh, &nhop, sizeof(nhop));
-               nexthop_add(&pbrms->nhg->nexthop, nh);
+               _nexthop_add(&pbrms->nhg->nexthop, nh);
 
                pbr_nht_add_individual_nexthop(pbrms);
                pbr_map_check(pbrms);
        }
 
-       if (nhop.type == NEXTHOP_TYPE_IFINDEX) {
+       if (nhop.type == NEXTHOP_TYPE_IFINDEX
+           || (nhop.type == NEXTHOP_TYPE_IPV6_IFINDEX
+               && IN6_IS_ADDR_LINKLOCAL(&nhop.gate.ipv6))) {
                struct interface *ifp;
 
                ifp = if_lookup_by_index(nhop.ifindex, nhop.vrf_id);
@@ -346,9 +386,64 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd,
        return CMD_SUCCESS;
 }
 
+DEFPY(pbr_map_vrf, pbr_map_vrf_cmd,
+      "[no] set vrf <NAME$vrf_name|unchanged>",
+      NO_STR
+      "Set for the PBR-MAP\n"
+      "Specify the VRF for this map\n"
+      "The VRF Name\n"
+      "Use the interface's VRF for lookup\n")
+{
+       struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+       int ret = CMD_SUCCESS;
+
+       if (no) {
+               pbr_map_delete_vrf(pbrms);
+
+               /* Reset all data */
+               pbrms->nhs_installed = false;
+               pbrms->vrf_name[0] = '\0';
+               pbrms->vrf_lookup = false;
+               pbrms->vrf_unchanged = false;
+
+               goto done;
+       }
+
+       if (pbrms->nhgrp_name || pbrms->nhg) {
+               vty_out(vty,
+                       "A `set nexthop/nexthop-group XX` command already exits, please remove that first\n");
+               ret = CMD_WARNING_CONFIG_FAILED;
+               goto done;
+       }
+
+       if (pbrms->vrf_lookup || pbrms->vrf_unchanged) {
+               vty_out(vty, SET_VRF_EXISTS_STR);
+               ret = CMD_WARNING_CONFIG_FAILED;
+               goto done;
+       }
+
+       if (vrf_name) {
+               if (!pbr_vrf_lookup_by_name(vrf_name)) {
+                       vty_out(vty, "Specified: %s is non-existent\n",
+                               vrf_name);
+                       ret = CMD_WARNING_CONFIG_FAILED;
+                       goto done;
+               }
+
+               pbrms->vrf_lookup = true;
+               strlcpy(pbrms->vrf_name, vrf_name, sizeof(pbrms->vrf_name));
+       } else
+               pbrms->vrf_unchanged = true;
+
+       pbr_map_check(pbrms);
+
+done:
+       return ret;
+}
+
 DEFPY (pbr_policy,
        pbr_policy_cmd,
-       "[no] pbr-policy NAME$mapname",
+       "[no] pbr-policy PBRMAP$mapname",
        NO_STR
        "Policy to use\n"
        "Name of the pbr-map to apply\n")
@@ -452,6 +547,8 @@ DEFPY (show_pbr_map,
                                vty_out(vty, "\tDST Match: %s\n",
                                        prefix2str(pbrms->dst, buf,
                                                   sizeof(buf)));
+                       if (pbrms->mark)
+                               vty_out(vty, "\tMARK Match: %u\n", pbrms->mark);
 
                        if (pbrms->nhgrp_name) {
                                vty_out(vty,
@@ -472,6 +569,12 @@ DEFPY (show_pbr_map,
                                                pbrms->internal_nhg_name),
                                        pbr_nht_get_table(
                                                pbrms->internal_nhg_name));
+                       } else if (pbrms->vrf_unchanged) {
+                               vty_out(vty,
+                                       "\tVRF Unchanged (use interface vrf)\n");
+                       } else if (pbrms->vrf_lookup) {
+                               vty_out(vty, "\tVRF Lookup: %s\n",
+                                       pbrms->vrf_name);
                        } else {
                                vty_out(vty,
                                        "\tNexthop-Group: Unknown Installed: 0(0)\n");
@@ -631,6 +734,15 @@ static int pbr_vty_map_config_write_sequence(struct vty *vty,
                vty_out(vty, " match dst-ip %s\n",
                        prefix2str(pbrms->dst, buff, sizeof(buff)));
 
+       if (pbrms->mark)
+               vty_out(vty, " match mark %u\n", pbrms->mark);
+
+       if (pbrms->vrf_unchanged)
+               vty_out(vty, " set vrf unchanged\n");
+
+       if (pbrms->vrf_lookup)
+               vty_out(vty, " set vrf %s\n", pbrms->vrf_name);
+
        if (pbrms->nhgrp_name)
                vty_out(vty, " set nexthop-group %s\n", pbrms->nhgrp_name);
 
@@ -661,8 +773,27 @@ static int pbr_vty_map_config_write(struct vty *vty)
        return 1;
 }
 
+static void pbr_map_completer(vector comps, struct cmd_token *token)
+{
+       struct pbr_map *pbrm;
+
+       RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps)
+               vector_set(comps, XSTRDUP(MTYPE_COMPLETION, pbrm->name));
+}
+
+static const struct cmd_variable_handler pbr_map_name[] = {
+       {
+               .tokenname = "PBRMAP", .completions = pbr_map_completer,
+       },
+       {
+               .completions = NULL
+       }
+};
+
 void pbr_vty_init(void)
 {
+       cmd_variable_handler_register(pbr_map_name);
+
        install_node(&interface_node,
                     pbr_interface_config_write);
        if_cmd_init();
@@ -684,8 +815,10 @@ void pbr_vty_init(void)
        install_element(INTERFACE_NODE, &pbr_policy_cmd);
        install_element(PBRMAP_NODE, &pbr_map_match_src_cmd);
        install_element(PBRMAP_NODE, &pbr_map_match_dst_cmd);
+       install_element(PBRMAP_NODE, &pbr_map_match_mark_cmd);
        install_element(PBRMAP_NODE, &pbr_map_nexthop_group_cmd);
        install_element(PBRMAP_NODE, &pbr_map_nexthop_cmd);
+       install_element(PBRMAP_NODE, &pbr_map_vrf_cmd);
        install_element(VIEW_NODE, &show_pbr_cmd);
        install_element(VIEW_NODE, &show_pbr_map_cmd);
        install_element(VIEW_NODE, &show_pbr_interface_cmd);