summaryrefslogtreecommitdiff
path: root/ospf6d/ospf6_interface.c
diff options
context:
space:
mode:
Diffstat (limited to 'ospf6d/ospf6_interface.c')
-rw-r--r--ospf6d/ospf6_interface.c696
1 files changed, 516 insertions, 180 deletions
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index 621cc36a0c..a169b9c60e 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -36,6 +36,7 @@
#include "ospf6_message.h"
#include "ospf6_route.h"
#include "ospf6_area.h"
+#include "ospf6_abr.h"
#include "ospf6_interface.h"
#include "ospf6_neighbor.h"
#include "ospf6_intra.h"
@@ -45,11 +46,12 @@
#include "ospf6_zebra.h"
#include "lib/json.h"
-DEFINE_MTYPE_STATIC(OSPF6D, CFG_PLIST_NAME, "configured prefix list names")
-DEFINE_QOBJ_TYPE(ospf6_interface)
+DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_IF, "OSPF6 interface");
+DEFINE_MTYPE_STATIC(OSPF6D, CFG_PLIST_NAME, "configured prefix list names");
+DEFINE_QOBJ_TYPE(ospf6_interface);
DEFINE_HOOK(ospf6_interface_change,
(struct ospf6_interface * oi, int state, int old_state),
- (oi, state, old_state))
+ (oi, state, old_state));
unsigned char conf_debug_ospf6_interface = 0;
@@ -108,7 +110,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;
@@ -183,6 +185,8 @@ struct ospf6_interface *ospf6_interface_create(struct interface *ifp)
oi = XCALLOC(MTYPE_OSPF6_IF, sizeof(struct ospf6_interface));
+ oi->obuf = ospf6_fifo_new();
+
oi->area = (struct ospf6_area *)NULL;
oi->neighbor_list = list_new();
oi->neighbor_list->cmp = ospf6_neighbor_cmp;
@@ -241,6 +245,8 @@ void ospf6_interface_delete(struct ospf6_interface *oi)
QOBJ_UNREG(oi);
+ ospf6_fifo_free(oi->obuf);
+
for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
ospf6_neighbor_delete(on);
@@ -271,11 +277,12 @@ void ospf6_interface_delete(struct ospf6_interface *oi)
if (oi->plist_name)
XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name);
- ospf6_bfd_info_free(&(oi->bfd_info));
-
/* disable from area list if possible */
ospf6_area_interface_delete(oi);
+ /* Free BFD allocated data. */
+ XFREE(MTYPE_TMP, oi->bfd_config.profile);
+
XFREE(MTYPE_OSPF6_IF, oi);
}
@@ -328,31 +335,6 @@ ospf6_interface_get_linklocal_address(struct interface *ifp)
return l;
}
-void ospf6_interface_if_add(struct interface *ifp)
-{
- struct ospf6_interface *oi;
- unsigned int iobuflen;
-
- oi = (struct ospf6_interface *)ifp->info;
- if (oi == NULL)
- return;
-
- /* Try to adjust I/O buffer size with IfMtu */
- if (oi->ifmtu == 0)
- oi->ifmtu = ifp->mtu6;
- iobuflen = ospf6_iobuf_size(ifp->mtu6);
- if (oi->ifmtu > iobuflen) {
- if (IS_OSPF6_DEBUG_INTERFACE)
- zlog_debug(
- "Interface %s: IfMtu is adjusted to I/O buffer size: %d.",
- ifp->name, iobuflen);
- oi->ifmtu = iobuflen;
- }
-
- /* interface start */
- ospf6_interface_state_update(oi->interface);
-}
-
void ospf6_interface_state_update(struct interface *ifp)
{
struct ospf6_interface *oi;
@@ -388,7 +370,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);
@@ -453,7 +435,7 @@ void ospf6_interface_connected_route_update(struct interface *ifp)
}
}
- route = ospf6_route_create();
+ route = ospf6_route_create(oi->area->ospf6);
memcpy(&route->prefix, c->address, sizeof(struct prefix));
apply_mask(&route->prefix);
route->type = OSPF6_DEST_TYPE_NETWORK;
@@ -472,8 +454,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;
@@ -482,7 +464,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) {
@@ -492,7 +477,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)
@@ -523,6 +509,8 @@ static void ospf6_interface_state_change(uint8_t next_state,
}
hook_call(ospf6_interface_change, oi, next_state, prev_state);
+
+ return 0;
}
@@ -679,6 +667,43 @@ static uint8_t dr_election(struct ospf6_interface *oi)
return next_state;
}
+#ifdef __FreeBSD__
+
+#include <ifaddrs.h>
+
+static bool ifmaddr_check(ifindex_t ifindex, struct in6_addr *addr)
+{
+ struct ifmaddrs *ifmap, *ifma;
+ struct sockaddr_dl *sdl;
+ struct sockaddr_in6 *sin6;
+ bool found = false;
+
+ if (getifmaddrs(&ifmap) != 0)
+ return false;
+
+ for (ifma = ifmap; ifma; ifma = ifma->ifma_next) {
+ if (ifma->ifma_name == NULL || ifma->ifma_addr == NULL)
+ continue;
+ if (ifma->ifma_name->sa_family != AF_LINK)
+ continue;
+ if (ifma->ifma_addr->sa_family != AF_INET6)
+ continue;
+ sdl = (struct sockaddr_dl *)ifma->ifma_name;
+ sin6 = (struct sockaddr_in6 *)ifma->ifma_addr;
+ if (sdl->sdl_index == ifindex
+ && memcmp(&sin6->sin6_addr, addr, IPV6_MAX_BYTELEN) == 0) {
+ found = true;
+ break;
+ }
+ }
+
+ if (ifmap)
+ freeifmaddrs(ifmap);
+
+ return found;
+}
+
+#endif /* __FreeBSD__ */
/* Interface State Machine */
int interface_up(struct thread *thread)
@@ -692,11 +717,7 @@ int interface_up(struct thread *thread)
if (!oi->type_cfg)
oi->type = ospf6_default_iftype(oi->interface);
- /*
- * Remove old pointer. If this thread wasn't a timer this
- * operation won't make a difference, because it is already NULL.
- */
- oi->thread_sso = NULL;
+ thread_cancel(&oi->thread_sso);
if (IS_OSPF6_DEBUG_INTERFACE)
zlog_debug("Interface Event %s: [InterfaceUp]",
@@ -704,20 +725,17 @@ int interface_up(struct thread *thread)
/* check physical interface is up */
if (!if_is_operative(oi->interface)) {
- if (IS_OSPF6_DEBUG_INTERFACE)
- zlog_debug(
- "Interface %s is down, can't execute [InterfaceUp]",
- oi->interface->name);
+ zlog_warn("Interface %s is down, can't execute [InterfaceUp]",
+ oi->interface->name);
return 0;
}
/* check interface has a link-local address */
if (!(ospf6_interface_get_linklocal_address(oi->interface)
- || if_is_loopback(oi->interface))) {
- if (IS_OSPF6_DEBUG_INTERFACE)
- zlog_debug(
- "Interface %s has no link local address, can't execute [InterfaceUp]",
- oi->interface->name);
+ || if_is_loopback_or_vrf(oi->interface))) {
+ zlog_warn(
+ "Interface %s has no link local address, can't execute [InterfaceUp]",
+ oi->interface->name);
return 0;
}
@@ -734,31 +752,33 @@ int interface_up(struct thread *thread)
/* If no area assigned, return */
if (oi->area == NULL) {
- zlog_debug(
- "%s: Not scheduleing Hello for %s as there is no area assigned yet",
+ zlog_warn(
+ "%s: Not scheduling Hello for %s as there is no area assigned yet",
__func__, oi->interface->name);
return 0;
}
#ifdef __FreeBSD__
/*
- * XXX: Schedule IPv6 group join for later, otherwise we might
- * lose the multicast group registration caused by IPv6 group
- * leave race.
+ * There's a delay in FreeBSD between issuing a command to leave a
+ * multicast group and an actual leave. If we execute "no router ospf6"
+ * and "router ospf6" fast enough, we can end up in a situation when OS
+ * performs the leave later than it performs the join and the interface
+ * remains without a multicast group. We have to do the join only after
+ * the interface actually left the group.
*/
- if (oi->sso_try_cnt == 0) {
- oi->sso_try_cnt++;
- zlog_info("Scheduling %s for sso", oi->interface->name);
+ if (ifmaddr_check(oi->interface->ifindex, &allspfrouters6)) {
+ zlog_info(
+ "Interface %s is still in all routers group, rescheduling for SSO",
+ oi->interface->name);
thread_add_timer(master, interface_up, oi,
OSPF6_INTERFACE_SSO_RETRY_INT,
&oi->thread_sso);
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,
@@ -781,14 +801,16 @@ 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);
}
/* decide next interface state */
- if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
+ if (oi->type == OSPF_IFTYPE_LOOPBACK) {
+ ospf6_interface_state_change(OSPF6_INTERFACE_LOOPBACK, oi);
+ } else if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
ospf6_interface_state_change(OSPF6_INTERFACE_POINTTOPOINT, oi);
} else if (oi->priority == 0)
ospf6_interface_state_change(OSPF6_INTERFACE_DROTHER, oi);
@@ -873,13 +895,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);
@@ -890,6 +905,27 @@ 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);
+
+ /* deal with write fifo */
+ ospf6_fifo_flush(oi->obuf);
+ if (oi->on_write_q) {
+ listnode_delete(ospf6->oi_write_q, oi);
+ if (list_isempty(ospf6->oi_write_q))
+ thread_cancel(&ospf6->t_write);
+ oi->on_write_q = 0;
+ }
+
+ ospf6_interface_state_change(OSPF6_INTERFACE_DOWN, oi);
+
return 0;
}
@@ -1147,23 +1183,59 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp,
for (ALL_LSDB(oi->lsack_list, lsa, lsanext))
vty_out(vty, " %s\n", lsa->name);
}
- ospf6_bfd_show_info(vty, oi->bfd_info, 1, json_obj, use_json);
+
+ /* BFD specific. */
+ if (oi->bfd_config.enabled) {
+ if (use_json) {
+ struct json_object *json_bfd = json_object_new_object();
+
+ json_object_int_add(
+ json_bfd, "detectMultiplier",
+ oi->bfd_config.detection_multiplier);
+ json_object_int_add(json_bfd, "rxMinInterval",
+ oi->bfd_config.min_rx);
+ json_object_int_add(json_bfd, "txMinInterval",
+ oi->bfd_config.min_tx);
+ json_object_object_add(json_obj, "peerBfdInfo",
+ json_bfd);
+ } else {
+ vty_out(vty,
+ " BFD: Detect Multiplier: %d, Min Rx interval: %d, Min Tx interval: %d\n",
+ oi->bfd_config.detection_multiplier,
+ oi->bfd_config.min_rx, oi->bfd_config.min_tx);
+ }
+ }
+
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;
@@ -1171,9 +1243,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",
@@ -1200,9 +1271,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);
@@ -1214,6 +1284,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;
}
@@ -1221,7 +1327,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;
@@ -1231,7 +1337,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");
@@ -1332,17 +1438,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;
@@ -1356,7 +1454,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",
@@ -1396,7 +1494,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",
@@ -1405,94 +1503,275 @@ 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;
+ }
+
+ 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);
+ 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;
+ }
+ }
- FOR_ALL_INTERFACES (vrf, ifp) {
- oi = (struct ospf6_interface *)ifp->info;
- if (oi == NULL)
- continue;
+ return CMD_SUCCESS;
+}
+
+void ospf6_interface_start(struct ospf6_interface *oi)
+{
+ struct ospf6 *ospf6;
+ struct ospf6_area *oa;
+
+ if (oi->area_id_format == OSPF6_AREA_FMT_UNSET)
+ return;
+
+ if (oi->area)
+ return;
+
+ ospf6 = ospf6_lookup_by_vrf_id(oi->interface->vrf_id);
+ if (!ospf6)
+ return;
+
+ oa = ospf6_area_lookup(oi->area_id, ospf6);
+ if (oa == NULL)
+ oa = ospf6_area_create(oi->area_id, ospf6, oi->area_id_format);
+
+ /* attach interface to area */
+ listnode_add(oa->if_list, oi);
+ oi->area = oa;
+
+ SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
+
+ /* start up */
+ ospf6_interface_enable(oi);
+
+ /* If the router is ABR, originate summary routes */
+ if (ospf6_check_and_set_router_abr(ospf6))
+ ospf6_abr_enable_area(oa);
+}
+
+void ospf6_interface_stop(struct ospf6_interface *oi)
+{
+ struct ospf6_area *oa;
+
+ oa = oi->area;
+ if (!oa)
+ return;
+
+ ospf6_interface_disable(oi);
+
+ listnode_delete(oa->if_list, oi);
+ oi->area = NULL;
+
+ if (oa->if_list->count == 0) {
+ UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
+ ospf6_abr_disable_area(oa);
+ }
+}
+
+/* interface variable set command */
+DEFUN (ipv6_ospf6_area,
+ ipv6_ospf6_area_cmd,
+ "ipv6 ospf6 area <A.B.C.D|(0-4294967295)>",
+ IP6_STR
+ OSPF6_STR
+ "Specify the OSPF6 area ID\n"
+ "OSPF6 area ID in IPv4 address notation\n"
+ "OSPF6 area ID in decimal notation\n")
+{
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+ struct ospf6_interface *oi;
+ int idx_ipv4 = 3;
+ uint32_t area_id;
+ int format;
+
+ assert(ifp);
- ospf6_route_table_show(vty, idx_prefix, argc, argv,
- oi->route_connected, uj);
+ oi = (struct ospf6_interface *)ifp->info;
+ if (oi == NULL)
+ oi = ospf6_interface_create(ifp);
+ assert(oi);
+
+ if (oi->area) {
+ vty_out(vty, "%s already attached to Area %s\n",
+ oi->interface->name, oi->area->name);
+ return CMD_SUCCESS;
+ }
+
+ if (str2area_id(argv[idx_ipv4]->arg, &area_id, &format)) {
+ vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
}
+ oi->area_id = area_id;
+ oi->area_id_format = format;
+
+ ospf6_interface_start(oi);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_ipv6_ospf6_area,
+ no_ipv6_ospf6_area_cmd,
+ "no ipv6 ospf6 area [<A.B.C.D|(0-4294967295)>]",
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "Specify the OSPF6 area ID\n"
+ "OSPF6 area ID in IPv4 address notation\n"
+ "OSPF6 area ID in decimal notation\n")
+{
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+ struct ospf6_interface *oi;
+
+ assert(ifp);
+
+ oi = (struct ospf6_interface *)ifp->info;
+ if (oi == NULL)
+ oi = ospf6_interface_create(ifp);
+ assert(oi);
+
+ ospf6_interface_stop(oi);
+
+ oi->area_id = 0;
+ oi->area_id_format = OSPF6_AREA_FMT_UNSET;
+
return CMD_SUCCESS;
}
-/* interface variable set command */
DEFUN (ipv6_ospf6_ifmtu,
ipv6_ospf6_ifmtu_cmd,
"ipv6 ospf6 ifmtu (1-65535)",
@@ -1622,12 +1901,11 @@ DEFUN (ipv6_ospf6_cost,
return CMD_WARNING_CONFIG_FAILED;
}
+ SET_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST);
if (oi->cost == lcost)
return CMD_SUCCESS;
oi->cost = lcost;
- SET_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST);
-
ospf6_interface_force_recalculate_cost(oi);
return CMD_SUCCESS;
@@ -1715,6 +1993,38 @@ DEFUN (no_auto_cost_reference_bandwidth,
}
+DEFUN (ospf6_write_multiplier,
+ ospf6_write_multiplier_cmd,
+ "write-multiplier (1-100)",
+ "Write multiplier\n"
+ "Maximum number of interface serviced per write\n")
+{
+ VTY_DECLVAR_CONTEXT(ospf6, o);
+ uint32_t write_oi_count;
+
+ write_oi_count = strtol(argv[1]->arg, NULL, 10);
+ if (write_oi_count < 1 || write_oi_count > 100) {
+ vty_out(vty, "write-multiplier value is invalid\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ o->write_oi_count = write_oi_count;
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf6_write_multiplier,
+ no_ospf6_write_multiplier_cmd,
+ "no write-multiplier (1-100)",
+ NO_STR
+ "Write multiplier\n"
+ "Maximum number of interface serviced per write\n")
+{
+ VTY_DECLVAR_CONTEXT(ospf6, o);
+
+ o->write_oi_count = OSPF6_WRITE_INTERFACE_COUNT_DEFAULT;
+ return CMD_SUCCESS;
+}
+
DEFUN (ipv6_ospf6_hellointerval,
ipv6_ospf6_hellointerval_cmd,
"ipv6 ospf6 hello-interval (1-65535)",
@@ -1873,10 +2183,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;
}
@@ -1978,7 +2291,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);
@@ -2182,21 +2495,30 @@ 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;
+ char buf[INET_ADDRSTRLEN];
FOR_ALL_INTERFACES (vrf, ifp) {
oi = (struct ospf6_interface *)ifp->info;
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);
+ if (oi->area_id_format != OSPF6_AREA_FMT_UNSET) {
+ area_id2str(buf, sizeof(buf), oi->area_id,
+ oi->area_id_format);
+ vty_out(vty, " ipv6 ospf6 area %s\n", buf);
+ }
if (oi->c_ifmtu)
vty_out(vty, " ipv6 ospf6 ifmtu %d\n", oi->c_ifmtu);
@@ -2248,21 +2570,28 @@ static int config_write_ospf6_interface(struct vty *vty)
return 0;
}
-static int config_write_ospf6_interface(struct vty *vty);
-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,
-};
+/* 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 ospf6_ifp_create(struct interface *ifp)
{
if (IS_OSPF6_DEBUG_ZEBRA(RECV))
zlog_debug("Zebra Interface add: %s index %d mtu %d", ifp->name,
ifp->ifindex, ifp->mtu6);
- ospf6_interface_if_add(ifp);
+
+ if (ifp->info)
+ ospf6_interface_start(ifp->info);
return 0;
}
@@ -2303,14 +2632,16 @@ static int ospf6_ifp_destroy(struct interface *ifp)
zlog_debug("Zebra Interface delete: %s index %d mtu %d",
ifp->name, ifp->ifindex, ifp->mtu6);
+ if (ifp->info)
+ ospf6_interface_stop(ifp->info);
+
return 0;
}
void ospf6_interface_init(void)
{
/* Install interface node. */
- install_node(&interface_node);
- if_cmd_init();
+ if_cmd_init(config_write_interface);
if_zapi_callbacks(ospf6_ifp_create, ospf6_ifp_up,
ospf6_ifp_down, ospf6_ifp_destroy);
@@ -2320,6 +2651,8 @@ void ospf6_interface_init(void)
&show_ipv6_ospf6_interface_ifname_prefix_cmd);
install_element(VIEW_NODE, &show_ipv6_ospf6_interface_traffic_cmd);
+ install_element(INTERFACE_NODE, &ipv6_ospf6_area_cmd);
+ install_element(INTERFACE_NODE, &no_ipv6_ospf6_area_cmd);
install_element(INTERFACE_NODE, &ipv6_ospf6_cost_cmd);
install_element(INTERFACE_NODE, &no_ipv6_ospf6_cost_cmd);
install_element(INTERFACE_NODE, &ipv6_ospf6_ifmtu_cmd);
@@ -2354,10 +2687,13 @@ void ospf6_interface_init(void)
/* reference bandwidth commands */
install_element(OSPF6_NODE, &auto_cost_reference_bandwidth_cmd);
install_element(OSPF6_NODE, &no_auto_cost_reference_bandwidth_cmd);
+ /* write-multiplier commands */
+ install_element(OSPF6_NODE, &ospf6_write_multiplier_cmd);
+ install_element(OSPF6_NODE, &no_ospf6_write_multiplier_cmd);
}
/* Clear the specified interface structure */
-static void ospf6_interface_clear(struct vty *vty, struct interface *ifp)
+void ospf6_interface_clear(struct interface *ifp)
{
struct ospf6_interface *oi;
@@ -2395,7 +2731,7 @@ DEFUN (clear_ipv6_ospf6_interface,
if (argc == 4) /* Clear all the ospfv3 interfaces. */
{
FOR_ALL_INTERFACES (vrf, ifp)
- ospf6_interface_clear(vty, ifp);
+ ospf6_interface_clear(ifp);
} else /* Interface name is specified. */
{
if ((ifp = if_lookup_by_name(argv[idx_ifname]->arg,
@@ -2405,7 +2741,7 @@ DEFUN (clear_ipv6_ospf6_interface,
argv[idx_ifname]->arg);
return CMD_WARNING;
}
- ospf6_interface_clear(vty, ifp);
+ ospf6_interface_clear(ifp);
}
return CMD_SUCCESS;