diff options
Diffstat (limited to 'ospfd/ospf_vty.c')
| -rw-r--r-- | ospfd/ospf_vty.c | 621 |
1 files changed, 486 insertions, 135 deletions
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index a49143873e..f1848f1eaf 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -201,6 +201,9 @@ DEFUN_NOSH (router_ospf, struct ospf *ospf = NULL; int ret = CMD_SUCCESS; u_short instance = 0; + struct vrf *vrf = NULL; + struct route_node *rn; + struct interface *ifp; ospf = ospf_cmd_lookup_ospf(vty, argv, argc, 1, &instance); if (!ospf) @@ -219,6 +222,34 @@ DEFUN_NOSH (router_ospf, instance, ospf->name ? ospf->name : "NIL", ospf->vrf_id, ospf->oi_running); VTY_PUSH_CONTEXT(OSPF_NODE, ospf); + + /* Activate 'ip ospf area x' configured interfaces for given + * vrf. Activate area on vrf x aware interfaces. + * vrf_enable callback calls router_id_update which + * internally will call ospf_if_update to trigger + * network_run_state + */ + vrf = vrf_lookup_by_id(ospf->vrf_id); + + FOR_ALL_INTERFACES (vrf, ifp) { + struct ospf_if_params *params; + + params = IF_DEF_PARAMS(ifp); + if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) { + for (rn = route_top(ospf->networks); rn; + rn = route_next(rn)) { + if (rn->info != NULL) { + vty_out(vty, + "Interface %s has area config but please remove all network commands first.\n", + ifp->name); + return ret; + } + } + ospf_interface_area_set(ospf, ifp); + ospf->if_ospf_cli_count++; + } + } + ospf_router_id_update(ospf); } @@ -570,6 +601,11 @@ DEFUN (ospf_network_area, if (ospf->if_ospf_cli_count > 0) { vty_out(vty, "Please remove all ip ospf area x.x.x.x commands first.\n"); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s ospf vrf %s num of %u ip osp area x config", + __PRETTY_FUNCTION__, + ospf->name ? ospf->name : "NIL", + ospf->if_ospf_cli_count); return CMD_WARNING_CONFIG_FAILED; } @@ -1541,7 +1577,7 @@ DEFUN (ospf_area_nssa, "OSPF area ID as a decimal value\n" "Configure OSPF area as nssa\n") { - return ospf_area_nssa_cmd_handler(vty, argc, argv, 1, 0); + return ospf_area_nssa_cmd_handler(vty, argc, argv, 0, 0); } DEFUN (ospf_area_nssa_no_summary, @@ -7926,7 +7962,7 @@ DEFUN (ip_ospf_area, else ospf = ospf_lookup_instance(instance); - if (ospf == NULL) { + if (instance && ospf == NULL) { params = IF_DEF_PARAMS(ifp); if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) { UNSET_IF_PARAM(params, if_area); @@ -7971,11 +8007,13 @@ DEFUN (ip_ospf_area, ospf_if_update_params((ifp), (addr)); } - for (rn = route_top(ospf->networks); rn; rn = route_next(rn)) { - if (rn->info != NULL) { - vty_out(vty, - "Please remove all network commands first.\n"); - return CMD_WARNING_CONFIG_FAILED; + if (ospf) { + for (rn = route_top(ospf->networks); rn; rn = route_next(rn)) { + if (rn->info != NULL) { + vty_out(vty, + "Please remove all network commands first.\n"); + return CMD_WARNING_CONFIG_FAILED; + } } } @@ -7985,8 +8023,11 @@ DEFUN (ip_ospf_area, params->if_area = area_id; params->if_area_id_fmt = format; } - ospf_interface_area_set(ospf, ifp); - ospf->if_ospf_cli_count++; + + if (ospf) { + ospf_interface_area_set(ospf, ifp); + ospf->if_ospf_cli_count++; + } return CMD_SUCCESS; } @@ -8361,10 +8402,10 @@ DEFUN (no_ospf_default_information_originate, ospf_external_lsa_flush(ospf, DEFAULT_ROUTE, &p, 0); - if ((ext = ospf_external_lookup(DEFAULT_ROUTE, 0)) - && EXTERNAL_INFO(ext)) { - ospf_external_info_delete(DEFAULT_ROUTE, 0, p); - ospf_external_del(DEFAULT_ROUTE, 0); + ext = ospf_external_lookup(ospf, DEFAULT_ROUTE, 0); + if (ext && EXTERNAL_INFO(ext)) { + ospf_external_info_delete(ospf, DEFAULT_ROUTE, 0, p); + ospf_external_del(ospf, DEFAULT_ROUTE, 0); } red = ospf_redist_lookup(ospf, DEFAULT_ROUTE, 0); @@ -8828,188 +8869,438 @@ static void config_write_stub_router(struct vty *vty, struct ospf *ospf) } static void show_ip_ospf_route_network(struct vty *vty, struct ospf *ospf, - struct route_table *rt) + struct route_table *rt, + json_object *json) { struct route_node *rn; struct ospf_route * or ; struct listnode *pnode, *pnnode; struct ospf_path *path; + json_object *json_route = NULL, *json_nexthop_array = NULL, + *json_nexthop = NULL; - vty_out(vty, "============ OSPF network routing table ============\n"); + if (!json) + vty_out(vty, "============ OSPF network routing table ============\n"); - for (rn = route_top(rt); rn; rn = route_next(rn)) - if ((or = rn->info) != NULL) { - char buf1[19]; - snprintf(buf1, 19, "%s/%d", inet_ntoa(rn->p.u.prefix4), - rn->p.prefixlen); - - switch (or->path_type) { - case OSPF_PATH_INTER_AREA: - if (or->type == OSPF_DESTINATION_NETWORK) + for (rn = route_top(rt); rn; rn = route_next(rn)) { + if ((or = rn->info) == NULL) + continue; + char buf1[PREFIX2STR_BUFFER]; + + memset(buf1, 0, sizeof(buf1)); + prefix2str(&rn->p, buf1, sizeof(buf1)); + + json_route = json_object_new_object(); + if (json) { + json_object_object_add(json, buf1, json_route); + json_object_to_json_string_ext(json, + JSON_C_TO_STRING_NOSLASHESCAPE); + + } + + switch (or->path_type) { + case OSPF_PATH_INTER_AREA: + if (or->type == OSPF_DESTINATION_NETWORK) { + if (json) { + json_object_string_add(json_route, + "routeType", + "N IA"); + json_object_int_add(json_route, + "cost", + or->cost); + json_object_string_add( + json_route, + "area", + inet_ntoa( + or->u.std.area_id)); + } else { vty_out(vty, - "N IA %-18s [%d] area: %s\n", + "N IA %-18s [%d] area: %s\n", buf1, or->cost, - inet_ntoa(or->u.std.area_id)); - else if (or->type == OSPF_DESTINATION_DISCARD) + inet_ntoa(or->u.std.area_id)); + } + } else if (or->type == + OSPF_DESTINATION_DISCARD) { + if (json) { + json_object_string_add(json_route, + "routeType", + "D IA"); + } else { vty_out(vty, "D IA %-18s Discard entry\n", buf1); - break; - case OSPF_PATH_INTRA_AREA: + } + } + break; + case OSPF_PATH_INTRA_AREA: + if (json) { + json_object_string_add(json_route, + "routeType", "N"); + json_object_int_add(json_route, "cost", + or->cost); + json_object_string_add(json_route, + "area", inet_ntoa(or->u.std.area_id)); + } else { vty_out(vty, "N %-18s [%d] area: %s\n", buf1, or->cost, inet_ntoa(or->u.std.area_id)); - break; - default: - break; } + break; + default: + break; + } - if (or->type == OSPF_DESTINATION_NETWORK) - for (ALL_LIST_ELEMENTS(or->paths, pnode, pnnode, - path)) { - if (if_lookup_by_index(path->ifindex, - ospf->vrf_id)) { - if (path->nexthop.s_addr == 0) - vty_out(vty, - "%24s directly attached to %s\n", - "", + if (or->type == OSPF_DESTINATION_NETWORK) { + if (json) { + json_nexthop_array = json_object_new_array(); + json_object_object_add(json_route, "nexthops", + json_nexthop_array); + } + + for (ALL_LIST_ELEMENTS(or->paths, pnode, pnnode, + path)) { + if (json) { + json_nexthop = + json_object_new_object(); + json_object_array_add(json_nexthop_array, + json_nexthop); + } + if (if_lookup_by_index(path->ifindex, + ospf->vrf_id)) { + + if (path->nexthop.s_addr == 0) { + if (json) { + json_object_string_add( + json_nexthop, + "ip", + " "); + json_object_string_add( + json_nexthop, + "directly attached to", ifindex2ifname( - path->ifindex, - ospf->vrf_id)); - else + path->ifindex, + ospf->vrf_id)); + } else { vty_out(vty, - "%24s via %s, %s\n", - "", + "%24s directly attached to %s\n", + "", + ifindex2ifname( + path->ifindex, + ospf->vrf_id)); + } + } else { + if (json) { + json_object_string_add( + json_nexthop, + "ip", inet_ntoa( - path->nexthop), + path->nexthop)); + json_object_string_add( + json_nexthop, + "via", ifindex2ifname( - path->ifindex, - ospf->vrf_id)); + path->ifindex, + ospf->vrf_id)); + } else { + vty_out(vty, + "%24s via %s, %s\n", + "", + inet_ntoa( + path->nexthop), + ifindex2ifname( + path->ifindex, + ospf->vrf_id)); + } } } + } } - vty_out(vty, "\n"); + if (!json) + json_object_free(json_route); + } + if (!json) + vty_out(vty, "\n"); } static void show_ip_ospf_route_router(struct vty *vty, struct ospf *ospf, - struct route_table *rtrs) + struct route_table *rtrs, + json_object *json) { struct route_node *rn; struct ospf_route * or ; struct listnode *pnode; struct listnode *node; struct ospf_path *path; + json_object *json_route = NULL, *json_nexthop_array = NULL, + *json_nexthop = NULL; - vty_out(vty, "============ OSPF router routing table =============\n"); - for (rn = route_top(rtrs); rn; rn = route_next(rn)) - if (rn->info) { - int flag = 0; + if (!json) + vty_out(vty, "============ OSPF router routing table =============\n"); + + for (rn = route_top(rtrs); rn; rn = route_next(rn)) { + if (rn->info == NULL) + continue; + int flag = 0; + json_route = json_object_new_object(); + if (json) { + json_object_object_add(json, + inet_ntoa(rn->p.u.prefix4), + json_route); + json_object_string_add(json_route, "routeType", + "R "); + } else { vty_out(vty, "R %-15s ", inet_ntoa(rn->p.u.prefix4)); + } - for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node, - or)) { - if (flag++) + for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node, + or)) { + if (flag++) { + if (!json) vty_out(vty, "%24s", ""); + } - /* Show path. */ + /* Show path. */ + if (json) { + json_object_int_add(json_route, "cost", + or->cost); + json_object_string_add(json_route, + "area", + inet_ntoa(or->u.std.area_id)); + if (or->path_type == + OSPF_PATH_INTER_AREA) + json_object_boolean_true_add( + json_route, + "IA"); + if (or->u.std.flags & ROUTER_LSA_BORDER) + json_object_string_add( + json_route, + "routerType", + "abr"); + else if (or->u.std.flags & + ROUTER_LSA_EXTERNAL) + json_object_string_add( + json_route, + "routerType", + "asbr"); + } else { vty_out(vty, "%s [%d] area: %s", - (or->path_type == OSPF_PATH_INTER_AREA - ? "IA" - : " "), - or->cost, inet_ntoa(or->u.std.area_id)); + (or->path_type == OSPF_PATH_INTER_AREA + ? "IA" + : " "), + or->cost, inet_ntoa(or->u.std.area_id)); /* Show flags. */ vty_out(vty, "%s%s\n", - (or->u.std.flags & ROUTER_LSA_BORDER - ? ", ABR" - : ""), - (or->u.std.flags & ROUTER_LSA_EXTERNAL - ? ", ASBR" - : "")); - - for (ALL_LIST_ELEMENTS_RO(or->paths, pnode, - path)) { - if (if_lookup_by_index(path->ifindex, - ospf->vrf_id)) { - if (path->nexthop.s_addr == 0) - vty_out(vty, - "%24s directly attached to %s\n", - "", + (or->u.std.flags & ROUTER_LSA_BORDER + ? ", ABR" + : ""), + (or->u.std.flags & ROUTER_LSA_EXTERNAL + ? ", ASBR" + : "")); + } + + if (json) { + json_nexthop_array = + json_object_new_array(); + json_object_object_add(json_route, "nexthops", + json_nexthop_array); + } + + for (ALL_LIST_ELEMENTS_RO(or->paths, pnode, + path)) { + if (json) { + json_nexthop = + json_object_new_object(); + json_object_array_add( + json_nexthop_array, + json_nexthop); + } + if (if_lookup_by_index(path->ifindex, + ospf->vrf_id)) { + if (path->nexthop.s_addr == 0) { + if (json) { + json_object_string_add( + json_nexthop, + "ip", + " "); + json_object_string_add( + json_nexthop, + "directly attached to", ifindex2ifname( path->ifindex, ospf->vrf_id)); - else + } else { vty_out(vty, - "%24s via %s, %s\n", - "", - inet_ntoa( - path->nexthop), + "%24s directly attached to %s\n", + "", + ifindex2ifname( + path->ifindex, + ospf->vrf_id)); + } + } else { + if (json) { + json_object_string_add( + json_nexthop, + "ip", + inet_ntoa(path->nexthop)); + json_object_string_add( + json_nexthop, + "via", ifindex2ifname( path->ifindex, ospf->vrf_id)); + } else { + vty_out(vty, + "%24s via %s, %s\n", + "", + inet_ntoa( + path->nexthop), + ifindex2ifname( + path->ifindex, + ospf->vrf_id)); + } } } } } - vty_out(vty, "\n"); + if (!json) + json_object_free(json_route); + } + if (!json) + vty_out(vty, "\n"); } static void show_ip_ospf_route_external(struct vty *vty, struct ospf *ospf, - struct route_table *rt) + struct route_table *rt, + json_object *json) { struct route_node *rn; struct ospf_route *er; struct listnode *pnode, *pnnode; struct ospf_path *path; + json_object *json_route = NULL, *json_nexthop_array = NULL, + *json_nexthop = NULL; - vty_out(vty, "============ OSPF external routing table ===========\n"); - for (rn = route_top(rt); rn; rn = route_next(rn)) - if ((er = rn->info) != NULL) { - char buf1[19]; - snprintf(buf1, 19, "%s/%d", inet_ntoa(rn->p.u.prefix4), - rn->p.prefixlen); + if (!json) + vty_out(vty, "============ OSPF external routing table ===========\n"); + + for (rn = route_top(rt); rn; rn = route_next(rn)) { + if ((er = rn->info) == NULL) + continue; + + char buf1[19]; - switch (er->path_type) { - case OSPF_PATH_TYPE1_EXTERNAL: + snprintf(buf1, 19, "%s/%d", inet_ntoa(rn->p.u.prefix4), + rn->p.prefixlen); + json_route = json_object_new_object(); + if (json) { + json_object_object_add(json, buf1, json_route); + json_object_to_json_string_ext(json, + JSON_C_TO_STRING_NOSLASHESCAPE); + + } + + switch (er->path_type) { + case OSPF_PATH_TYPE1_EXTERNAL: + if (json) { + json_object_string_add(json_route, + "routeType", + "N E1"); + json_object_int_add(json_route, "cost", + er->cost); + } else { vty_out(vty, - "N E1 %-18s [%d] tag: %" ROUTE_TAG_PRI - "\n", - buf1, er->cost, er->u.ext.tag); - break; - case OSPF_PATH_TYPE2_EXTERNAL: + "N E1 %-18s [%d] tag: %" ROUTE_TAG_PRI + "\n", + buf1, er->cost, er->u.ext.tag); + } + break; + case OSPF_PATH_TYPE2_EXTERNAL: + if (json) { + json_object_string_add(json_route, + "routeType", + "N E2"); + json_object_int_add(json_route, "cost", + er->cost); + } else { vty_out(vty, - "N E2 %-18s [%d/%d] tag: %" ROUTE_TAG_PRI - "\n", - buf1, er->cost, er->u.ext.type2_cost, + "N E2 %-18s [%d/%d] tag: %" + ROUTE_TAG_PRI + "\n", buf1, er->cost, + er->u.ext.type2_cost, er->u.ext.tag); - break; } + break; + } - for (ALL_LIST_ELEMENTS(er->paths, pnode, pnnode, - path)) { - if (if_lookup_by_index(path->ifindex, - ospf->vrf_id)) { - if (path->nexthop.s_addr == 0) - vty_out(vty, - "%24s directly attached to %s\n", - "", + if (json) { + json_nexthop_array = json_object_new_array(); + json_object_object_add(json_route, "nexthops", + json_nexthop_array); + } + + for (ALL_LIST_ELEMENTS(er->paths, pnode, pnnode, + path)) { + if (json) { + json_nexthop = json_object_new_object(); + json_object_array_add(json_nexthop_array + ,json_nexthop); + } + + if (if_lookup_by_index(path->ifindex, + ospf->vrf_id)) { + if (path->nexthop.s_addr == 0) { + if (json) { + json_object_string_add( + json_nexthop, + "ip", + " "); + json_object_string_add( + json_nexthop, + "directly attached to", ifindex2ifname( - path->ifindex, - ospf->vrf_id)); - else + path->ifindex, + ospf->vrf_id)); + } else { vty_out(vty, - "%24s via %s, %s\n", - "", + "%24s directly attached to %s\n", + "", + ifindex2ifname( + path->ifindex, + ospf->vrf_id)); + } + } else { + if (json) { + json_object_string_add( + json_nexthop, + "ip", inet_ntoa( - path->nexthop), + path->nexthop)); + json_object_string_add( + json_nexthop, + "via", ifindex2ifname( - path->ifindex, - ospf->vrf_id)); + path->ifindex, + ospf->vrf_id)); + } else { + vty_out(vty, + "%24s via %s, %s\n", + "", + inet_ntoa( + path->nexthop), + ifindex2ifname( + path->ifindex, + ospf->vrf_id)); + } } } } - vty_out(vty, "\n"); + if (!json) + json_object_free(json_route); + } + if (!json) + vty_out(vty, "\n"); } static int show_ip_ospf_border_routers_common(struct vty *vty, @@ -9030,7 +9321,7 @@ static int show_ip_ospf_border_routers_common(struct vty *vty, show_ip_ospf_route_network (vty, ospf->new_table); */ /* Show Router routes. */ - show_ip_ospf_route_router(vty, ospf, ospf->new_rtrs); + show_ip_ospf_route_router(vty, ospf, ospf->new_rtrs, NULL); vty_out(vty, "\n"); @@ -9113,12 +9404,22 @@ DEFUN (show_ip_ospf_instance_border_routers, } static int show_ip_ospf_route_common(struct vty *vty, struct ospf *ospf, - u_char use_vrf) + json_object *json, u_char use_vrf) { + json_object *json_vrf = NULL; + if (ospf->instance) vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); - ospf_show_vrf_name(ospf, vty, NULL, use_vrf); + + if (json) { + if (use_vrf) + json_vrf = json_object_new_object(); + else + json_vrf = json; + } + + ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf); if (ospf->new_table == NULL) { vty_out(vty, "No OSPF routing information exist\n"); @@ -9126,28 +9427,42 @@ static int show_ip_ospf_route_common(struct vty *vty, struct ospf *ospf, } /* Show Network routes. */ - show_ip_ospf_route_network(vty, ospf, ospf->new_table); + show_ip_ospf_route_network(vty, ospf, ospf->new_table, json_vrf); /* Show Router routes. */ - show_ip_ospf_route_router(vty, ospf, ospf->new_rtrs); + show_ip_ospf_route_router(vty, ospf, ospf->new_rtrs, json_vrf); /* Show AS External routes. */ - show_ip_ospf_route_external(vty, ospf, ospf->old_external_route); + show_ip_ospf_route_external(vty, ospf, ospf->old_external_route, + json_vrf); - vty_out(vty, "\n"); + if (json) { + if (use_vrf) { + //json_object_object_add(json_vrf, "areas", json_areas); + if (ospf->vrf_id == VRF_DEFAULT) + json_object_object_add(json, "default", + json_vrf); + else + json_object_object_add(json, ospf->name, + json_vrf); + } + } else { + vty_out(vty, "\n"); + } return CMD_SUCCESS; } DEFUN (show_ip_ospf_route, show_ip_ospf_route_cmd, - "show ip ospf [vrf <NAME|all>] route", + "show ip ospf [vrf <NAME|all>] route [json]", SHOW_STR IP_STR "OSPF information\n" VRF_CMD_HELP_STR "All VRFs\n" - "OSPF routing table\n") + "OSPF routing table\n" + JSON_STR) { struct ospf *ospf = NULL; struct listnode *node = NULL; @@ -9157,6 +9472,11 @@ DEFUN (show_ip_ospf_route, int inst = 0; int idx_vrf = 0; u_char use_vrf = 0; + u_char uj = use_json(argc, argv); + json_object *json = NULL; + + if (uj) + json = json_object_new_object(); OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); @@ -9167,23 +9487,44 @@ DEFUN (show_ip_ospf_route, for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { if (!ospf->oi_running) continue; - ret = show_ip_ospf_route_common(vty, ospf, + ret = show_ip_ospf_route_common(vty, ospf, json, use_vrf); } + + if (uj) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext(json, + JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } + return ret; } ospf = ospf_lookup_by_inst_name(inst, vrf_name); - if (ospf == NULL || !ospf->oi_running) + if (ospf == NULL || !ospf->oi_running) { + if (uj) + json_object_free(json); return CMD_SUCCESS; + } } else { /* Display default ospf (instance 0) info */ ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); - if (ospf == NULL || !ospf->oi_running) + if (ospf == NULL || !ospf->oi_running) { + if (uj) + json_object_free(json); return CMD_SUCCESS; + } + } + + if (ospf) { + ret = show_ip_ospf_route_common(vty, ospf, json, use_vrf); + if (uj) + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); } - if (ospf) - ret = show_ip_ospf_route_common(vty, ospf, use_vrf); + if (uj) + json_object_free(json); return ret; } @@ -9209,7 +9550,7 @@ DEFUN (show_ip_ospf_instance_route, if (!ospf->oi_running) return CMD_SUCCESS; - return show_ip_ospf_route_common(vty, ospf, 0); + return show_ip_ospf_route_common(vty, ospf, NULL, 0); } @@ -9633,6 +9974,9 @@ static int config_write_ospf_area(struct vty *vty, struct ospf *ospf) " area %s nssa translate-always\n", buf); break; + case OSPF_NSSA_ROLE_CANDIDATE: + vty_out(vty, " area %s nssa \n", buf); + break; } if (area->no_summary) vty_out(vty, @@ -10061,7 +10405,14 @@ static int ospf_config_write(struct vty *vty) return write; for (ALL_LIST_ELEMENTS_RO(om->ospf, ospf_node, ospf)) { - if (ospf->oi_running) + /* VRF Default check if it is running. + * Upon daemon start, there could be default instance + * in absence of 'router ospf'/oi_running is disabled. */ + if (ospf->vrf_id == VRF_DEFAULT && ospf->oi_running) + write += ospf_config_write_one(vty, ospf); + /* For Non-Default VRF simply display the configuration, + * even if it is not oi_running. */ + else if (ospf->vrf_id != VRF_DEFAULT) write += ospf_config_write_one(vty, ospf); } return write; |
