diff options
Diffstat (limited to 'pimd/pim_cmd.c')
-rw-r--r-- | pimd/pim_cmd.c | 425 |
1 files changed, 420 insertions, 5 deletions
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 110408001..e1dfb0006 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -60,6 +60,7 @@ #include "pim_ssm.h" #include "pim_nht.h" #include "pim_bfd.h" +#include "pim_vxlan.h" #include "bfd.h" #ifndef VTYSH_EXTRACT_PL @@ -1963,7 +1964,7 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty, json = json_object_new_object(); } else { vty_out(vty, - "Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G)"); + "Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN"); vty_out(vty, "\nInstalled Source Group IIF OIL\n"); } @@ -2092,7 +2093,7 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty, } else { if (first_oif) { first_oif = 0; - vty_out(vty, "%s(%c%c%c%c)", out_ifname, + vty_out(vty, "%s(%c%c%c%c%c)", out_ifname, (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) ? 'I' @@ -2102,6 +2103,10 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty, ? 'J' : ' ', (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_VXLAN) + ? 'V' + : ' ', + (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) ? 'S' : ' ', @@ -2110,7 +2115,7 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty, ? '*' : ' '); } else - vty_out(vty, ", %s(%c%c%c%c)", + vty_out(vty, ", %s(%c%c%c%c%c)", out_ifname, (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) @@ -2121,6 +2126,10 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty, ? 'J' : ' ', (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_VXLAN) + ? 'V' + : ' ', + (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) ? 'S' : ' ', @@ -4672,6 +4681,11 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill, json_ifp_out, "protocolIgmp"); if (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_VXLAN) + json_object_boolean_true_add( + json_ifp_out, "protocolVxlan"); + + if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) json_object_boolean_true_add( json_ifp_out, "protocolSource"); @@ -4714,6 +4728,11 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill, } if (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_VXLAN) { + strcpy(proto, "VxLAN"); + } + + if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) { strcpy(proto, "SRC"); } @@ -5825,7 +5844,8 @@ static int pim_cmd_igmp_start(struct vty *vty, struct interface *ifp) pim_ifp = ifp->info; if (!pim_ifp) { - pim_ifp = pim_if_new(ifp, true, false, false); + pim_ifp = pim_if_new(ifp, true, false, false, + false /*vxlan_term*/); if (!pim_ifp) { vty_out(vty, "Could not enable IGMP on interface %s\n", ifp->name); @@ -6436,7 +6456,8 @@ static int pim_cmd_interface_add(struct interface *ifp) struct pim_interface *pim_ifp = ifp->info; if (!pim_ifp) { - pim_ifp = pim_if_new(ifp, false, true, false); + pim_ifp = pim_if_new(ifp, false, true, false, + false /*vxlan_term*/); if (!pim_ifp) { return 0; } @@ -7435,6 +7456,29 @@ DEFUN (no_debug_pim_zebra, return CMD_SUCCESS; } +DEFUN (debug_pim_vxlan, + debug_pim_vxlan_cmd, + "debug pim vxlan", + DEBUG_STR + DEBUG_PIM_STR + DEBUG_PIM_VXLAN_STR) +{ + PIM_DO_DEBUG_VXLAN; + return CMD_SUCCESS; +} + +DEFUN (no_debug_pim_vxlan, + no_debug_pim_vxlan_cmd, + "no debug pim vxlan", + NO_STR + DEBUG_STR + DEBUG_PIM_STR + DEBUG_PIM_VXLAN_STR) +{ + PIM_DONT_DEBUG_VXLAN; + return CMD_SUCCESS; +} + DEFUN (debug_msdp, debug_msdp_cmd, "debug msdp", @@ -8736,6 +8780,369 @@ DEFUN (show_ip_msdp_sa_sg_vrf_all, return CMD_SUCCESS; } +struct pim_sg_cache_walk_data { + struct vty *vty; + json_object *json; + json_object *json_group; + struct in_addr addr; + bool addr_match; +}; + +static void pim_show_vxlan_sg_entry(struct pim_vxlan_sg *vxlan_sg, + struct pim_sg_cache_walk_data *cwd) +{ + struct vty *vty = cwd->vty; + json_object *json = cwd->json; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + json_object *json_row; + bool installed = (vxlan_sg->up)?TRUE:FALSE; + const char *iif_name = vxlan_sg->iif?vxlan_sg->iif->name:"-"; + const char *oif_name; + + if (pim_vxlan_is_orig_mroute(vxlan_sg)) + oif_name = vxlan_sg->orig_oif?vxlan_sg->orig_oif->name:""; + else + oif_name = vxlan_sg->term_oif?vxlan_sg->term_oif->name:""; + + if (cwd->addr_match && (vxlan_sg->sg.src.s_addr != cwd->addr.s_addr) && + (vxlan_sg->sg.grp.s_addr != cwd->addr.s_addr)) { + return; + } + pim_inet4_dump("<src?>", vxlan_sg->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("<grp?>", vxlan_sg->sg.grp, grp_str, sizeof(grp_str)); + if (json) { + json_object_object_get_ex(json, grp_str, &cwd->json_group); + + if (!cwd->json_group) { + cwd->json_group = json_object_new_object(); + json_object_object_add(json, grp_str, + cwd->json_group); + } + + json_row = json_object_new_object(); + json_object_string_add(json_row, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + json_object_string_add(json_row, "input", iif_name); + json_object_string_add(json_row, "output", oif_name); + if (installed) + json_object_boolean_true_add(json_row, "installed"); + else + json_object_boolean_false_add(json_row, "installed"); + json_object_object_add(cwd->json_group, src_str, json_row); + } else { + vty_out(vty, "%-15s %-15s %-15s %-15s %-5s\n", + src_str, grp_str, iif_name, oif_name, + installed?"I":""); + } +} + +static void pim_show_vxlan_sg_hash_entry(struct hash_backet *backet, void *arg) +{ + pim_show_vxlan_sg_entry((struct pim_vxlan_sg *)backet->data, + (struct pim_sg_cache_walk_data *)arg); +} + +static void pim_show_vxlan_sg(struct pim_instance *pim, + struct vty *vty, bool uj) +{ + json_object *json = NULL; + struct pim_sg_cache_walk_data cwd; + + if (uj) { + json = json_object_new_object(); + } else { + vty_out(vty, "Codes: I -> installed\n"); + vty_out(vty, + "Source Group Input Output Flags\n"); + } + + memset(&cwd, 0, sizeof(cwd)); + cwd.vty = vty; + cwd.json = json; + hash_iterate(pim->vxlan.sg_hash, pim_show_vxlan_sg_hash_entry, &cwd); + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } +} + +static void pim_show_vxlan_sg_match_addr(struct pim_instance *pim, + struct vty *vty, char *addr_str, bool uj) +{ + json_object *json = NULL; + struct pim_sg_cache_walk_data cwd; + int result = 0; + + memset(&cwd, 0, sizeof(cwd)); + result = inet_pton(AF_INET, addr_str, &cwd.addr); + if (result <= 0) { + vty_out(vty, "Bad address %s: errno=%d: %s\n", addr_str, + errno, safe_strerror(errno)); + return; + } + + if (uj) { + json = json_object_new_object(); + } else { + vty_out(vty, "Codes: I -> installed\n"); + vty_out(vty, + "Source Group Input Output Flags\n"); + } + + cwd.vty = vty; + cwd.json = json; + cwd.addr_match = TRUE; + hash_iterate(pim->vxlan.sg_hash, pim_show_vxlan_sg_hash_entry, &cwd); + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } +} + +static void pim_show_vxlan_sg_one(struct pim_instance *pim, + struct vty *vty, char *src_str, char *grp_str, bool uj) +{ + json_object *json = NULL; + struct prefix_sg sg; + int result = 0; + struct pim_vxlan_sg *vxlan_sg; + const char *iif_name; + bool installed; + const char *oif_name; + + result = inet_pton(AF_INET, src_str, &sg.src); + if (result <= 0) { + vty_out(vty, "Bad src address %s: errno=%d: %s\n", src_str, + errno, safe_strerror(errno)); + return; + } + result = inet_pton(AF_INET, grp_str, &sg.grp); + if (result <= 0) { + vty_out(vty, "Bad grp address %s: errno=%d: %s\n", grp_str, + errno, safe_strerror(errno)); + return; + } + + sg.family = AF_INET; + sg.prefixlen = IPV4_MAX_BITLEN; + if (uj) + json = json_object_new_object(); + + vxlan_sg = pim_vxlan_sg_find(pim, &sg); + if (vxlan_sg) { + installed = (vxlan_sg->up)?TRUE:FALSE; + iif_name = vxlan_sg->iif?vxlan_sg->iif->name:"-"; + + if (pim_vxlan_is_orig_mroute(vxlan_sg)) + oif_name = + vxlan_sg->orig_oif?vxlan_sg->orig_oif->name:""; + else + oif_name = + vxlan_sg->term_oif?vxlan_sg->term_oif->name:""; + + if (uj) { + json_object_string_add(json, "source", src_str); + json_object_string_add(json, "group", grp_str); + json_object_string_add(json, "input", iif_name); + json_object_string_add(json, "output", oif_name); + if (installed) + json_object_boolean_true_add(json, "installed"); + else + json_object_boolean_false_add(json, + "installed"); + } else { + vty_out(vty, "SG : %s\n", vxlan_sg->sg_str); + vty_out(vty, " Input : %s\n", iif_name); + vty_out(vty, " Output : %s\n", oif_name); + vty_out(vty, " installed : %s\n", + installed?"yes":"no"); + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } +} + +DEFUN (show_ip_pim_vxlan_sg, + show_ip_pim_vxlan_sg_cmd, + "show ip pim [vrf NAME] vxlan-groups [A.B.C.D [A.B.C.D]] [json]", + SHOW_STR + IP_STR + PIM_STR + VRF_CMD_HELP_STR + "VxLAN BUM groups\n" + "source or group ip\n" + "group ip\n" + JSON_STR) +{ + bool uj = use_json(argc, argv); + struct vrf *vrf; + int idx = 2; + + vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + + if (!vrf) + return CMD_WARNING; + + char *src_ip = argv_find(argv, argc, "A.B.C.D", &idx) ? + argv[idx++]->arg:NULL; + char *grp_ip = idx < argc && argv_find(argv, argc, "A.B.C.D", &idx) ? + argv[idx]->arg:NULL; + + if (src_ip && grp_ip) + pim_show_vxlan_sg_one(vrf->info, vty, src_ip, grp_ip, uj); + else if (src_ip) + pim_show_vxlan_sg_match_addr(vrf->info, vty, src_ip, uj); + else + pim_show_vxlan_sg(vrf->info, vty, uj); + + return CMD_SUCCESS; +} + +static void pim_show_vxlan_sg_work(struct pim_instance *pim, + struct vty *vty, bool uj) +{ + json_object *json = NULL; + struct pim_sg_cache_walk_data cwd; + struct listnode *node; + struct pim_vxlan_sg *vxlan_sg; + + if (uj) { + json = json_object_new_object(); + } else { + vty_out(vty, "Codes: I -> installed\n"); + vty_out(vty, + "Source Group Input Flags\n"); + } + + memset(&cwd, 0, sizeof(cwd)); + cwd.vty = vty; + cwd.json = json; + for (ALL_LIST_ELEMENTS_RO(pim_vxlan_p->work_list, node, vxlan_sg)) + pim_show_vxlan_sg_entry(vxlan_sg, &cwd); + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } +} + +DEFUN_HIDDEN (show_ip_pim_vxlan_sg_work, + show_ip_pim_vxlan_sg_work_cmd, + "show ip pim [vrf NAME] vxlan-work [json]", + SHOW_STR + IP_STR + PIM_STR + VRF_CMD_HELP_STR + "VxLAN work list\n" + JSON_STR) +{ + bool uj = use_json(argc, argv); + struct vrf *vrf; + int idx = 2; + + vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + + if (!vrf) + return CMD_WARNING; + + pim_show_vxlan_sg_work(vrf->info, vty, uj); + + return CMD_SUCCESS; +} + +DEFUN_HIDDEN (no_ip_pim_mlag, + no_ip_pim_mlag_cmd, + "no ip pim mlag", + NO_STR + IP_STR + PIM_STR + "MLAG\n") +{ + struct in_addr addr; + + addr.s_addr = 0; + pim_vxlan_mlag_update(TRUE /*mlag_enable*/, + FALSE /*peer_state*/, PIM_VXLAN_MLAG_ROLE_SECONDARY, + NULL/*peerlink*/, &addr); + + return CMD_SUCCESS; +} + +DEFUN_HIDDEN (ip_pim_mlag, + ip_pim_mlag_cmd, + "ip pim mlag INTERFACE role [primary|secondary] state [up|down] addr A.B.C.D", + IP_STR + PIM_STR + "MLAG\n" + "peerlink sub interface\n" + "MLAG role\n" + "MLAG role primary\n" + "MLAG role secondary\n" + "peer session state\n" + "peer session state up\n" + "peer session state down\n" + "configure PIP\n" + "unique ip address\n") +{ + struct interface *ifp; + const char *peerlink; + uint32_t role; + int idx; + bool peer_state; + int result; + struct in_addr reg_addr; + + idx = 3; + peerlink = argv[idx]->arg; + ifp = if_lookup_by_name(peerlink, VRF_DEFAULT); + if (!ifp) { + vty_out(vty, "No such interface name %s\n", peerlink); + return CMD_WARNING; + } + + idx += 2; + if (!strcmp(argv[idx]->arg, "primary")) { + role = PIM_VXLAN_MLAG_ROLE_PRIMARY; + } else if (!strcmp(argv[idx]->arg, "secondary")) { + role = PIM_VXLAN_MLAG_ROLE_SECONDARY; + } else { + vty_out(vty, "unknown MLAG role %s\n", argv[idx]->arg); + return CMD_WARNING; + } + + idx += 2; + if (!strcmp(argv[idx]->arg, "up")) { + peer_state = TRUE; + } else if (strcmp(argv[idx]->arg, "down")) { + peer_state = FALSE; + } else { + vty_out(vty, "unknown MLAG state %s\n", argv[idx]->arg); + return CMD_WARNING; + } + + idx += 2; + result = inet_pton(AF_INET, argv[idx]->arg, ®_addr); + if (result <= 0) { + vty_out(vty, "%% Bad reg address %s: errno=%d: %s\n", + argv[idx]->arg, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + pim_vxlan_mlag_update(TRUE, peer_state, role, ifp, ®_addr); + + return CMD_SUCCESS; +} + void pim_cmd_init(void) { install_node(&interface_node, @@ -8809,6 +9216,8 @@ void pim_cmd_init(void) install_element(VRF_NODE, &ip_pim_ecmp_rebalance_cmd); install_element(CONFIG_NODE, &no_ip_pim_ecmp_rebalance_cmd); install_element(VRF_NODE, &no_ip_pim_ecmp_rebalance_cmd); + install_element(CONFIG_NODE, &ip_pim_mlag_cmd); + install_element(CONFIG_NODE, &no_ip_pim_mlag_cmd); install_element(INTERFACE_NODE, &interface_ip_igmp_cmd); install_element(INTERFACE_NODE, &interface_no_ip_igmp_cmd); @@ -8935,6 +9344,8 @@ void pim_cmd_init(void) install_element(ENABLE_NODE, &no_debug_ssmpingd_cmd); install_element(ENABLE_NODE, &debug_pim_zebra_cmd); install_element(ENABLE_NODE, &no_debug_pim_zebra_cmd); + install_element(ENABLE_NODE, &debug_pim_vxlan_cmd); + install_element(ENABLE_NODE, &no_debug_pim_vxlan_cmd); install_element(ENABLE_NODE, &debug_msdp_cmd); install_element(ENABLE_NODE, &no_debug_msdp_cmd); install_element(ENABLE_NODE, &debug_msdp_events_cmd); @@ -8976,6 +9387,8 @@ void pim_cmd_init(void) install_element(CONFIG_NODE, &no_debug_ssmpingd_cmd); install_element(CONFIG_NODE, &debug_pim_zebra_cmd); install_element(CONFIG_NODE, &no_debug_pim_zebra_cmd); + install_element(CONFIG_NODE, &debug_pim_vxlan_cmd); + install_element(CONFIG_NODE, &no_debug_pim_vxlan_cmd); install_element(CONFIG_NODE, &debug_msdp_cmd); install_element(CONFIG_NODE, &no_debug_msdp_cmd); install_element(CONFIG_NODE, &debug_msdp_events_cmd); @@ -9003,6 +9416,8 @@ void pim_cmd_init(void) install_element(VIEW_NODE, &show_ip_msdp_mesh_group_vrf_all_cmd); install_element(VIEW_NODE, &show_ip_pim_ssm_range_cmd); install_element(VIEW_NODE, &show_ip_pim_group_type_cmd); + install_element(VIEW_NODE, &show_ip_pim_vxlan_sg_cmd); + install_element(VIEW_NODE, &show_ip_pim_vxlan_sg_work_cmd); install_element(INTERFACE_NODE, &interface_pim_use_source_cmd); install_element(INTERFACE_NODE, &interface_no_pim_use_source_cmd); /* Install BFD command */ |