X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=pbrd%2Fpbr_vty.c;h=bc4aa947a9c07922566af576d3d0e9ddfff361ef;hb=6fc3fed23c95da21887acb57a92c474e4d0ca3a4;hp=067d5c01fdfac621cebd1a0bf8fdc70dc88d8888;hpb=ecedbaa13b8f39011c8c3feed163b293605447de;p=mirror_frr.git diff --git a/pbrd/pbr_vty.c b/pbrd/pbr_vty.c index 067d5c01f..bc4aa947a 100644 --- a/pbrd/pbr_vty.c +++ b/pbrd/pbr_vty.c @@ -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, $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 ", + 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);