diff options
Diffstat (limited to 'pimd/pim_cmd.c')
| -rw-r--r-- | pimd/pim_cmd.c | 600 |
1 files changed, 564 insertions, 36 deletions
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 2d5acb87a9..9c1cb38012 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 @@ -1696,7 +1697,8 @@ static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp, } } -static void pim_show_join(struct pim_instance *pim, struct vty *vty, bool uj) +static void pim_show_join(struct pim_instance *pim, struct vty *vty, + struct prefix_sg *sg, bool uj) { struct pim_interface *pim_ifp; struct pim_ifchannel *ch; @@ -1718,6 +1720,12 @@ static void pim_show_join(struct pim_instance *pim, struct vty *vty, bool uj) continue; RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) { + if (sg->grp.s_addr != 0 + && sg->grp.s_addr != ch->sg.grp.s_addr) + continue; + if (sg->src.s_addr != 0 + && sg->src.s_addr != ch->sg.src.s_addr) + continue; pim_show_join_helper(vty, pim_ifp, ch, json, now, uj); } /* scan interface channels */ } @@ -1956,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"); } @@ -2085,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' @@ -2095,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' : ' ', @@ -2103,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) @@ -2114,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' : ' ', @@ -2295,6 +2311,41 @@ static void json_object_pim_upstream_add(json_object *json, /* XXX: need to print ths flag in the plain text display as well */ if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP) json_object_boolean_true_add(json, "sourceMsdp"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE) + json_object_boolean_true_add(json, "sendSGRptPrune"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_LHR) + json_object_boolean_true_add(json, "lastHopRouter"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY) + json_object_boolean_true_add(json, "disableKATExpiry"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_STATIC_IIF) + json_object_boolean_true_add(json, "staticIncomingInterface"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL) + json_object_boolean_true_add(json, + "allowIncomingInterfaceinOil"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA) + json_object_boolean_true_add(json, "noPimRegistrationData"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG) + json_object_boolean_true_add(json, "forcePimRegistration"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG) + json_object_boolean_true_add(json, "sourceVxlanOrigination"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM) + json_object_boolean_true_add(json, "sourceVxlanTermination"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN) + json_object_boolean_true_add(json, "mlagVxlan"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF) + json_object_boolean_true_add(json, + "mlagNonDesignatedForwarder"); } static const char * @@ -2335,7 +2386,7 @@ static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state, } static void pim_show_upstream(struct pim_instance *pim, struct vty *vty, - bool uj) + struct prefix_sg *sg, bool uj) { struct listnode *upnode; struct pim_upstream *up; @@ -2362,6 +2413,11 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty, char msdp_reg_timer[10]; char state_str[PIM_REG_STATE_STR_LEN]; + if (sg->grp.s_addr != 0 && sg->grp.s_addr != up->sg.grp.s_addr) + continue; + if (sg->src.s_addr != 0 && sg->src.s_addr != up->sg.src.s_addr) + continue; + pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); pim_time_uptime(uptime, sizeof(uptime), @@ -3777,24 +3833,45 @@ DEFUN (show_ip_pim_interface_vrf_all, return CMD_SUCCESS; } -DEFUN (show_ip_pim_join, +DEFPY (show_ip_pim_join, show_ip_pim_join_cmd, - "show ip pim [vrf NAME] join [json]", + "show ip pim [vrf NAME] join [A.B.C.D$s_or_g [A.B.C.D$g]] [json$json]", SHOW_STR IP_STR PIM_STR VRF_CMD_HELP_STR "PIM interface join information\n" + "The Source or Group\n" + "The Group\n" JSON_STR) { - int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - bool uj = use_json(argc, argv); + struct prefix_sg sg = {0}; + struct vrf *v; + bool uj = !!json; + struct pim_instance *pim; - if (!vrf) + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) { + vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf); return CMD_WARNING; + } + pim = pim_get_pim_instance(v->vrf_id); + + if (!pim) { + vty_out(vty, "%% Unable to find pim instance\n"); + return CMD_WARNING; + } + + if (s_or_g.s_addr != 0) { + if (g.s_addr != 0) { + sg.src = s_or_g; + sg.grp = g; + } else + sg.grp = s_or_g; + } - pim_show_join(vrf->info, vty, uj); + pim_show_join(pim, vty, &sg, uj); return CMD_SUCCESS; } @@ -3809,6 +3886,7 @@ DEFUN (show_ip_pim_join_vrf_all, "PIM interface join information\n" JSON_STR) { + struct prefix_sg sg = {0}; bool uj = use_json(argc, argv); struct vrf *vrf; bool first = true; @@ -3823,7 +3901,7 @@ DEFUN (show_ip_pim_join_vrf_all, first = false; } else vty_out(vty, "VRF: %s\n", vrf->name); - pim_show_join(vrf->info, vty, uj); + pim_show_join(vrf->info, vty, &sg, uj); } if (uj) vty_out(vty, "}\n"); @@ -4022,24 +4100,44 @@ DEFUN (show_ip_pim_state_vrf_all, return CMD_SUCCESS; } -DEFUN (show_ip_pim_upstream, +DEFPY (show_ip_pim_upstream, show_ip_pim_upstream_cmd, - "show ip pim [vrf NAME] upstream [json]", + "show ip pim [vrf NAME] upstream [A.B.C.D$s_or_g [A.B.C.D$g]] [json$json]", SHOW_STR IP_STR PIM_STR VRF_CMD_HELP_STR "PIM upstream information\n" + "The Source or Group\n" + "The Group\n" JSON_STR) { - int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - bool uj = use_json(argc, argv); + struct prefix_sg sg = {0}; + struct vrf *v; + bool uj = !!json; + struct pim_instance *pim; - if (!vrf) + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) { + vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf); + return CMD_WARNING; + } + pim = pim_get_pim_instance(v->vrf_id); + + if (!pim) { + vty_out(vty, "%% Unable to find pim instance\n"); return CMD_WARNING; + } - pim_show_upstream(vrf->info, vty, uj); + if (s_or_g.s_addr != 0) { + if (g.s_addr != 0) { + sg.src = s_or_g; + sg.grp = g; + } else + sg.grp = s_or_g; + } + pim_show_upstream(pim, vty, &sg, uj); return CMD_SUCCESS; } @@ -4054,6 +4152,7 @@ DEFUN (show_ip_pim_upstream_vrf_all, "PIM upstream information\n" JSON_STR) { + struct prefix_sg sg = {0}; bool uj = use_json(argc, argv); struct vrf *vrf; bool first = true; @@ -4068,7 +4167,7 @@ DEFUN (show_ip_pim_upstream_vrf_all, first = false; } else vty_out(vty, "VRF: %s\n", vrf->name); - pim_show_upstream(vrf->info, vty, uj); + pim_show_upstream(vrf->info, vty, &sg, uj); } return CMD_SUCCESS; @@ -4493,8 +4592,8 @@ DEFUN (show_ip_multicast_vrf_all, return CMD_SUCCESS; } -static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill, - bool uj) +static void show_mroute(struct pim_instance *pim, struct vty *vty, + struct prefix_sg *sg, bool fill, bool uj) { struct listnode *node; struct channel_oil *c_oil; @@ -4531,6 +4630,13 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill, if (!c_oil->installed && !uj) continue; + if (sg->grp.s_addr != 0 && + sg->grp.s_addr != c_oil->oil.mfcc_mcastgrp.s_addr) + continue; + if (sg->src.s_addr != 0 && + sg->src.s_addr != c_oil->oil.mfcc_origin.s_addr) + continue; + pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str, sizeof(grp_str)); pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str, @@ -4617,6 +4723,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"); @@ -4659,6 +4770,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"); } @@ -4818,28 +4934,43 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill, } } -DEFUN (show_ip_mroute, +DEFPY (show_ip_mroute, show_ip_mroute_cmd, - "show ip mroute [vrf NAME] [fill] [json]", + "show ip mroute [vrf NAME] [A.B.C.D$s_or_g [A.B.C.D$g]] [fill$fill] [json$json]", SHOW_STR IP_STR MROUTE_STR VRF_CMD_HELP_STR + "The Source or Group\n" + "The Group\n" "Fill in Assumed data\n" JSON_STR) { - bool uj = use_json(argc, argv); - bool fill = false; - int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + struct prefix_sg sg = {0}; + struct pim_instance *pim; + struct vrf *v; - if (!vrf) + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) { + vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf); return CMD_WARNING; + } + pim = pim_get_pim_instance(v->vrf_id); - if (argv_find(argv, argc, "fill", &idx)) - fill = true; + if (!pim) { + vty_out(vty, "%% Unable to find pim instance\n"); + return CMD_WARNING; + } - show_mroute(vrf->info, vty, fill, uj); + if (s_or_g.s_addr != 0) { + if (g.s_addr != 0) { + sg.src = s_or_g; + sg.grp = g; + } else + sg.grp = s_or_g; + } + show_mroute(pim, vty, &sg, !!fill, !!json); return CMD_SUCCESS; } @@ -4853,6 +4984,7 @@ DEFUN (show_ip_mroute_vrf_all, "Fill in Assumed data\n" JSON_STR) { + struct prefix_sg sg = {0}; bool uj = use_json(argc, argv); int idx = 4; struct vrf *vrf; @@ -4872,7 +5004,7 @@ DEFUN (show_ip_mroute_vrf_all, first = false; } else vty_out(vty, "VRF: %s\n", vrf->name); - show_mroute(vrf->info, vty, fill, uj); + show_mroute(vrf->info, vty, &sg, fill, uj); } if (uj) vty_out(vty, "}\n"); @@ -5770,7 +5902,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); @@ -6381,7 +6514,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; } @@ -7380,6 +7514,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", @@ -8681,6 +8838,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, @@ -8754,6 +9274,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); @@ -8880,6 +9402,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); @@ -8921,6 +9445,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); @@ -8948,6 +9474,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 */ |
