diff options
Diffstat (limited to 'ospf6d/ospf6_interface.c')
| -rw-r--r-- | ospf6d/ospf6_interface.c | 372 |
1 files changed, 254 insertions, 118 deletions
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index f3af8b308f..b71d884fdc 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -109,7 +109,7 @@ static uint8_t ospf6_default_iftype(struct interface *ifp) { if (if_is_pointopoint(ifp)) return OSPF_IFTYPE_POINTOPOINT; - else if (if_is_loopback(ifp)) + else if (if_is_loopback_or_vrf(ifp)) return OSPF_IFTYPE_LOOPBACK; else return OSPF_IFTYPE_BROADCAST; @@ -390,7 +390,7 @@ void ospf6_interface_state_update(struct interface *ifp) if (if_is_operative(ifp) && (ospf6_interface_get_linklocal_address(oi->interface) - || if_is_loopback(oi->interface))) + || if_is_loopback_or_vrf(oi->interface))) thread_execute(master, interface_up, oi, 0); else thread_execute(master, interface_down, oi, 0); @@ -405,6 +405,7 @@ void ospf6_interface_connected_route_update(struct interface *ifp) struct connected *c; struct listnode *node, *nnode; struct in6_addr nh_addr; + int count = 0, max_addr_count; oi = (struct ospf6_interface *)ifp->info; if (oi == NULL) @@ -423,10 +424,22 @@ void ospf6_interface_connected_route_update(struct interface *ifp) /* update "route to advertise" interface route table */ ospf6_route_remove_all(oi->route_connected); + if (oi->ifmtu >= OSPF6_JUMBO_MTU) + max_addr_count = OSPF6_MAX_IF_ADDRS_JUMBO; + else + max_addr_count = OSPF6_MAX_IF_ADDRS; + for (ALL_LIST_ELEMENTS(oi->interface->connected, node, nnode, c)) { if (c->address->family != AF_INET6) continue; + /* number of interface addresses supported is based on MTU + * size of OSPFv3 packet + */ + count++; + if (count >= max_addr_count) + break; + CONTINUE_IF_ADDRESS_LINKLOCAL(IS_OSPF6_DEBUG_INTERFACE, c->address); CONTINUE_IF_ADDRESS_UNSPECIFIED(IS_OSPF6_DEBUG_INTERFACE, @@ -474,8 +487,8 @@ void ospf6_interface_connected_route_update(struct interface *ifp) OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area); } -static void ospf6_interface_state_change(uint8_t next_state, - struct ospf6_interface *oi) +static int ospf6_interface_state_change(uint8_t next_state, + struct ospf6_interface *oi) { uint8_t prev_state; struct ospf6 *ospf6; @@ -484,7 +497,10 @@ static void ospf6_interface_state_change(uint8_t next_state, oi->state = next_state; if (prev_state == next_state) - return; + return -1; + + if (!oi->area) + return -1; /* log */ if (IS_OSPF6_DEBUG_INTERFACE) { @@ -494,7 +510,8 @@ static void ospf6_interface_state_change(uint8_t next_state, ospf6_interface_state_str[next_state]); } oi->state_change++; - ospf6 = ospf6_lookup_by_vrf_id(oi->interface->vrf_id); + + ospf6 = oi->area->ospf6; if ((prev_state == OSPF6_INTERFACE_DR || prev_state == OSPF6_INTERFACE_BDR) @@ -525,6 +542,8 @@ static void ospf6_interface_state_change(uint8_t next_state, } hook_call(ospf6_interface_change, oi, next_state, prev_state); + + return 0; } @@ -715,7 +734,7 @@ int interface_up(struct thread *thread) /* check interface has a link-local address */ if (!(ospf6_interface_get_linklocal_address(oi->interface) - || if_is_loopback(oi->interface))) { + || if_is_loopback_or_vrf(oi->interface))) { if (IS_OSPF6_DEBUG_INTERFACE) zlog_debug( "Interface %s has no link local address, can't execute [InterfaceUp]", @@ -757,10 +776,8 @@ int interface_up(struct thread *thread) return 0; } #endif /* __FreeBSD__ */ - if (oi->area->ospf6) - ospf6 = oi->area->ospf6; - else - ospf6 = ospf6_lookup_by_vrf_id(oi->interface->vrf_id); + + ospf6 = oi->area->ospf6; /* Join AllSPFRouters */ if (ospf6_sso(oi->interface->ifindex, &allspfrouters6, IPV6_JOIN_GROUP, @@ -783,7 +800,7 @@ int interface_up(struct thread *thread) /* Schedule Hello */ if (!CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE) - && !if_is_loopback(oi->interface)) { + && !if_is_loopback_or_vrf(oi->interface)) { oi->thread_send_hello = NULL; thread_add_event(master, ospf6_hello_send, oi, 0, &oi->thread_send_hello); @@ -875,13 +892,6 @@ int interface_down(struct thread *thread) /* Stop trying to set socket options. */ THREAD_OFF(oi->thread_sso); - ospf6 = ospf6_lookup_by_vrf_id(oi->interface->vrf_id); - /* Leave AllSPFRouters */ - if (oi->state > OSPF6_INTERFACE_DOWN) - ospf6_sso(oi->interface->ifindex, &allspfrouters6, - IPV6_LEAVE_GROUP, ospf6->fd); - - ospf6_interface_state_change(OSPF6_INTERFACE_DOWN, oi); for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) ospf6_neighbor_delete(on); @@ -892,6 +902,18 @@ int interface_down(struct thread *thread) * DR election, as it is no longer valid. */ oi->drouter = oi->prev_drouter = htonl(0); oi->bdrouter = oi->prev_bdrouter = htonl(0); + + if (oi->area == NULL) + return 0; + + ospf6 = oi->area->ospf6; + /* Leave AllSPFRouters */ + if (oi->state > OSPF6_INTERFACE_DOWN) + ospf6_sso(oi->interface->ifindex, &allspfrouters6, + IPV6_LEAVE_GROUP, ospf6->fd); + + ospf6_interface_state_change(OSPF6_INTERFACE_DOWN, oi); + return 0; } @@ -1175,19 +1197,33 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp, return 0; } -/* show interface */ -DEFUN(show_ipv6_ospf6_interface, - show_ipv6_ospf6_interface_ifname_cmd, - "show ipv6 ospf6 interface [IFNAME] [json]", - SHOW_STR - IP6_STR - OSPF6_STR - INTERFACE_STR - IFNAME_STR - JSON_STR) +/* Find the global address to be used as a forwarding address in NSSA LSA.*/ +struct in6_addr *ospf6_interface_get_global_address(struct interface *ifp) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); - int idx_ifname = 4; + struct listnode *n; + struct connected *c; + struct in6_addr *l = (struct in6_addr *)NULL; + + /* for each connected address */ + for (ALL_LIST_ELEMENTS_RO(ifp->connected, n, c)) { + /* if family not AF_INET6, ignore */ + if (c->address->family != AF_INET6) + continue; + + if (!IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6)) + l = &c->address->u.prefix6; + } + return l; +} + + +static int show_ospf6_interface_common(struct vty *vty, vrf_id_t vrf_id, + int argc, struct cmd_token **argv, + int idx_ifname, int intf_idx, + int json_idx) +{ + + struct vrf *vrf = vrf_lookup_by_id(vrf_id); struct interface *ifp; json_object *json; json_object *json_int; @@ -1195,9 +1231,8 @@ DEFUN(show_ipv6_ospf6_interface, if (uj) { json = json_object_new_object(); - if (argc == 6) { - ifp = if_lookup_by_name(argv[idx_ifname]->arg, - VRF_DEFAULT); + if (argc == json_idx) { + ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id); json_int = json_object_new_object(); if (ifp == NULL) { json_object_string_add(json, "noSuchInterface", @@ -1224,9 +1259,8 @@ DEFUN(show_ipv6_ospf6_interface, json, JSON_C_TO_STRING_PRETTY)); json_object_free(json); } else { - if (argc == 5) { - ifp = if_lookup_by_name(argv[idx_ifname]->arg, - VRF_DEFAULT); + if (argc == intf_idx) { + ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id); if (ifp == NULL) { vty_out(vty, "No such Interface: %s\n", argv[idx_ifname]->arg); @@ -1238,6 +1272,42 @@ DEFUN(show_ipv6_ospf6_interface, ospf6_interface_show(vty, ifp, NULL, uj); } } + return CMD_SUCCESS; +} + +/* show interface */ +DEFUN(show_ipv6_ospf6_interface, show_ipv6_ospf6_interface_ifname_cmd, + "show ipv6 ospf6 [vrf <NAME|all>] interface [IFNAME] [json]", + SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR + "All VRFs\n" INTERFACE_STR IFNAME_STR JSON_STR) +{ + int idx_ifname = 4; + int intf_idx = 5; + int json_idx = 6; + struct listnode *node; + struct ospf6 *ospf6; + const char *vrf_name = NULL; + bool all_vrf = false; + int idx_vrf = 0; + + OSPF6_CMD_CHECK_RUNNING(); + OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + if (idx_vrf > 0) { + idx_ifname += 2; + intf_idx += 2; + json_idx += 2; + } + + for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) { + if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) { + show_ospf6_interface_common(vty, ospf6->vrf_id, argc, + argv, idx_ifname, intf_idx, + json_idx); + + if (!all_vrf) + break; + } + } return CMD_SUCCESS; } @@ -1245,7 +1315,7 @@ DEFUN(show_ipv6_ospf6_interface, static int ospf6_interface_show_traffic(struct vty *vty, struct interface *intf_ifp, int display_once, json_object *json, - bool use_json) + bool use_json, vrf_id_t vrf_id) { struct interface *ifp; struct vrf *vrf = NULL; @@ -1255,7 +1325,7 @@ static int ospf6_interface_show_traffic(struct vty *vty, if (intf_ifp) vrf = vrf_lookup_by_id(intf_ifp->vrf_id); else - vrf = vrf_lookup_by_id(VRF_DEFAULT); + vrf = vrf_lookup_by_id(vrf_id); if (!display_once && !use_json) { vty_out(vty, "\n"); @@ -1356,17 +1426,9 @@ static int ospf6_interface_show_traffic(struct vty *vty, return CMD_SUCCESS; } -/* show interface */ -DEFUN(show_ipv6_ospf6_interface_traffic, - show_ipv6_ospf6_interface_traffic_cmd, - "show ipv6 ospf6 interface traffic [IFNAME] [json]", - SHOW_STR - IP6_STR - OSPF6_STR - INTERFACE_STR - "Protocol Packet counters\n" - IFNAME_STR - JSON_STR) +static int ospf6_interface_show_traffic_common(struct vty *vty, int argc, + struct cmd_token **argv, + vrf_id_t vrf_id) { int idx_ifname = 0; int display_once = 0; @@ -1380,7 +1442,7 @@ DEFUN(show_ipv6_ospf6_interface_traffic, if (argv_find(argv, argc, "IFNAME", &idx_ifname)) { intf_name = argv[idx_ifname]->arg; - ifp = if_lookup_by_name(intf_name, VRF_DEFAULT); + ifp = if_lookup_by_name(intf_name, vrf_id); if (uj) { if (ifp == NULL) { json_object_string_add(json, "status", @@ -1420,7 +1482,7 @@ DEFUN(show_ipv6_ospf6_interface_traffic, } } - ospf6_interface_show_traffic(vty, ifp, display_once, json, uj); + ospf6_interface_show_traffic(vty, ifp, display_once, json, uj, vrf_id); if (uj) { vty_out(vty, "%s\n", @@ -1429,94 +1491,148 @@ DEFUN(show_ipv6_ospf6_interface_traffic, json_object_free(json); } + return CMD_SUCCESS; +} + +/* show interface */ +DEFUN(show_ipv6_ospf6_interface_traffic, show_ipv6_ospf6_interface_traffic_cmd, + "show ipv6 ospf6 [vrf <NAME|all>] interface traffic [IFNAME] [json]", + SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR + "All VRFs\n" INTERFACE_STR + "Protocol Packet counters\n" IFNAME_STR JSON_STR) +{ + struct ospf6 *ospf6; + struct listnode *node; + const char *vrf_name = NULL; + bool all_vrf = false; + int idx_vrf = 0; + + OSPF6_CMD_CHECK_RUNNING(); + OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + + for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) { + if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) { + ospf6_interface_show_traffic_common(vty, argc, argv, + ospf6->vrf_id); + + if (!all_vrf) + break; + } + } return CMD_SUCCESS; } -DEFUN (show_ipv6_ospf6_interface_ifname_prefix, - show_ipv6_ospf6_interface_ifname_prefix_cmd, - "show ipv6 ospf6 interface IFNAME prefix\ +DEFUN(show_ipv6_ospf6_interface_ifname_prefix, + show_ipv6_ospf6_interface_ifname_prefix_cmd, + "show ipv6 ospf6 [vrf <NAME|all>] interface IFNAME prefix\ [<\ detail\ |<X:X::X:X|X:X::X:X/M> [<match|detail>]\ >] [json]", - SHOW_STR - IP6_STR - OSPF6_STR - INTERFACE_STR - IFNAME_STR - "Display connected prefixes to advertise\n" - "Display details of the prefixes\n" - OSPF6_ROUTE_ADDRESS_STR - OSPF6_ROUTE_PREFIX_STR - OSPF6_ROUTE_MATCH_STR - "Display details of the prefixes\n" - JSON_STR) + SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR + "All VRFs\n" INTERFACE_STR IFNAME_STR + "Display connected prefixes to advertise\n" + "Display details of the prefixes\n" OSPF6_ROUTE_ADDRESS_STR + OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_MATCH_STR + "Display details of the prefixes\n" JSON_STR) { int idx_ifname = 4; int idx_prefix = 6; - struct interface *ifp; struct ospf6_interface *oi; bool uj = use_json(argc, argv); - ifp = if_lookup_by_name(argv[idx_ifname]->arg, VRF_DEFAULT); - if (ifp == NULL) { - vty_out(vty, "No such Interface: %s\n", argv[idx_ifname]->arg); - return CMD_WARNING; + struct ospf6 *ospf6; + struct listnode *node; + struct interface *ifp; + const char *vrf_name = NULL; + bool all_vrf = false; + int idx_vrf = 0; + + OSPF6_CMD_CHECK_RUNNING(); + OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + if (idx_vrf > 0) { + idx_ifname += 2; + idx_prefix += 2; } - oi = ifp->info; - if (oi == NULL) { - vty_out(vty, "OSPFv3 is not enabled on %s\n", - argv[idx_ifname]->arg); - return CMD_WARNING; - } + for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) { + if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) { + ifp = if_lookup_by_name(argv[idx_ifname]->arg, + ospf6->vrf_id); + if (ifp == NULL) { + vty_out(vty, "No such Interface: %s\n", + argv[idx_ifname]->arg); + return CMD_WARNING; + } - if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) { - vty_out(vty, "Interface %s not attached to area\n", - argv[idx_ifname]->arg); - return CMD_WARNING; - } + oi = ifp->info; + if (oi == NULL + || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) { + vty_out(vty, + "Interface %s not attached to area\n", + argv[idx_ifname]->arg); + return CMD_WARNING; + } - ospf6_route_table_show(vty, idx_prefix, argc, argv, oi->route_connected, - uj); + ospf6_route_table_show(vty, idx_prefix, argc, argv, + oi->route_connected, uj); + + if (!all_vrf) + break; + } + } return CMD_SUCCESS; } -DEFUN (show_ipv6_ospf6_interface_prefix, - show_ipv6_ospf6_interface_prefix_cmd, - "show ipv6 ospf6 interface prefix\ +DEFUN(show_ipv6_ospf6_interface_prefix, show_ipv6_ospf6_interface_prefix_cmd, + "show ipv6 ospf6 [vrf <NAME|all>] interface prefix\ [<\ detail\ |<X:X::X:X|X:X::X:X/M> [<match|detail>]\ >] [json]", - SHOW_STR - IP6_STR - OSPF6_STR - INTERFACE_STR - "Display connected prefixes to advertise\n" - "Display details of the prefixes\n" - OSPF6_ROUTE_ADDRESS_STR - OSPF6_ROUTE_PREFIX_STR - OSPF6_ROUTE_MATCH_STR - "Display details of the prefixes\n" - JSON_STR) + SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR + "All VRFs\n" INTERFACE_STR + "Display connected prefixes to advertise\n" + "Display details of the prefixes\n" OSPF6_ROUTE_ADDRESS_STR + OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_MATCH_STR + "Display details of the prefixes\n" JSON_STR) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); + struct vrf *vrf = NULL; int idx_prefix = 5; struct ospf6_interface *oi; struct interface *ifp; bool uj = use_json(argc, argv); - - FOR_ALL_INTERFACES (vrf, ifp) { - oi = (struct ospf6_interface *)ifp->info; - if (oi == NULL || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) - continue; - - ospf6_route_table_show(vty, idx_prefix, argc, argv, - oi->route_connected, uj); + struct listnode *node; + struct ospf6 *ospf6; + const char *vrf_name = NULL; + bool all_vrf = false; + int idx_vrf = 0; + + OSPF6_CMD_CHECK_RUNNING(); + OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + if (idx_vrf > 0) + idx_prefix += 2; + + for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) { + if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) { + vrf = vrf_lookup_by_id(ospf6->vrf_id); + FOR_ALL_INTERFACES (vrf, ifp) { + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL + || CHECK_FLAG(oi->flag, + OSPF6_INTERFACE_DISABLE)) + continue; + + ospf6_route_table_show(vty, idx_prefix, argc, + argv, + oi->route_connected, uj); + } + if (!all_vrf) + break; + } } return CMD_SUCCESS; @@ -1902,10 +2018,13 @@ DEFUN (ipv6_ospf6_priority, ? OSPF6_INTERFACE_PRIORITY : strtoul(argv[idx_number]->arg, NULL, 10); - if (oi->area && (oi->state == OSPF6_INTERFACE_DROTHER - || oi->state == OSPF6_INTERFACE_BDR - || oi->state == OSPF6_INTERFACE_DR)) - ospf6_interface_state_change(dr_election(oi), oi); + if (oi->area + && (oi->state == OSPF6_INTERFACE_DROTHER + || oi->state == OSPF6_INTERFACE_BDR + || oi->state == OSPF6_INTERFACE_DR)) { + if (ospf6_interface_state_change(dr_election(oi), oi) == -1) + OSPF6_LINK_LSA_SCHEDULE(oi); + } return CMD_SUCCESS; } @@ -2007,7 +2126,7 @@ DEFUN (no_ipv6_ospf6_passive, THREAD_OFF(oi->thread_sso); /* don't send hellos over loopback interface */ - if (!if_is_loopback(oi->interface)) + if (!if_is_loopback_or_vrf(oi->interface)) thread_add_event(master, ospf6_hello_send, oi, 0, &oi->thread_send_hello); @@ -2211,9 +2330,8 @@ DEFUN (no_ipv6_ospf6_network, return CMD_SUCCESS; } -static int config_write_ospf6_interface(struct vty *vty) +static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); struct ospf6_interface *oi; struct interface *ifp; @@ -2222,7 +2340,11 @@ static int config_write_ospf6_interface(struct vty *vty) if (oi == NULL) continue; - vty_frame(vty, "interface %s\n", oi->interface->name); + if (vrf->vrf_id == VRF_DEFAULT) + vty_frame(vty, "interface %s\n", oi->interface->name); + else + vty_frame(vty, "interface %s vrf %s\n", + oi->interface->name, vrf->name); if (ifp->desc) vty_out(vty, " description %s\n", ifp->desc); @@ -2277,13 +2399,27 @@ static int config_write_ospf6_interface(struct vty *vty) return 0; } -static int config_write_ospf6_interface(struct vty *vty); +/* Configuration write function for ospfd. */ +static int config_write_interface(struct vty *vty) +{ + int write = 0; + struct vrf *vrf = NULL; + + /* Display all VRF aware OSPF interface configuration */ + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + write += config_write_ospf6_interface(vty, vrf); + } + + return write; +} + +static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf); static struct cmd_node interface_node = { .name = "interface", .node = INTERFACE_NODE, .parent_node = CONFIG_NODE, .prompt = "%s(config-if)# ", - .config_write = config_write_ospf6_interface, + .config_write = config_write_interface, }; static int ospf6_ifp_create(struct interface *ifp) |
