summaryrefslogtreecommitdiff
path: root/ospf6d/ospf6_interface.c
diff options
context:
space:
mode:
authorIgor Ryzhov <iryzhov@nfware.com>2021-05-26 01:49:30 +0300
committerIgor Ryzhov <iryzhov@nfware.com>2021-06-08 21:38:09 +0300
commit42cabc552d50b3dbc658b88a27b75fd6a2f7bec5 (patch)
tree80f2fe12c51a8075e481376adc13eb37b90d7c54 /ospf6d/ospf6_interface.c
parent6869bb921e7b79aeb2b145ce0b98bec8af8cbc84 (diff)
ospf6d: fix interface area configuration
Currently the interface area is configured from the router node using "interface IFNAME area ID" command. There are multiple problems with this command: - it is not in line with all other interface-related commands - other parameters are configured from the interface node using "ipv6 ospf6" prefix - it is not in line with OSPFv2 - area is configured from the interface node using "ip ospf area" command - most importantly, it doesn't work correctly when the interface is in a different VRF - instead of configuring the interface, it creates a new fake interface and configuring it instead To fix all the problems, this commit adds a new command to the interface configuration node - "ipv6 ospf6 area ID". The purpose of the command is completely the same, but it works correctly in a multi-VRF environment. The old command is preserved for the backward compatibility, but the warning is added that it is deprecated because it doesn't work correctly with VRFs. Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
Diffstat (limited to 'ospf6d/ospf6_interface.c')
-rw-r--r--ospf6d/ospf6_interface.c177
1 files changed, 151 insertions, 26 deletions
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index b71d884fdc..148f2dc50d 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"
@@ -330,31 +331,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;
@@ -1638,7 +1614,143 @@ DEFUN(show_ipv6_ospf6_interface_prefix, show_ipv6_ospf6_interface_prefix_cmd,
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;
+
+ 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_is_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;
+ int ipv6_count = 0;
+
+ assert(ifp);
+
+ 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 more than OSPF6_MAX_IF_ADDRS are configured on this interface
+ * then don't allow ospfv3 to be configured
+ */
+ ipv6_count = connected_count_by_family(ifp, AF_INET6);
+ if (oi->ifmtu == OSPF6_DEFAULT_MTU && ipv6_count > OSPF6_MAX_IF_ADDRS) {
+ vty_out(vty,
+ "can not configure OSPFv3 on if %s, must have less than %d interface addresses but has %d addresses\n",
+ ifp->name, OSPF6_MAX_IF_ADDRS, ipv6_count);
+ return CMD_WARNING_CONFIG_FAILED;
+ } else if (oi->ifmtu >= OSPF6_JUMBO_MTU
+ && ipv6_count > OSPF6_MAX_IF_ADDRS_JUMBO) {
+ vty_out(vty,
+ "can not configure OSPFv3 on if %s, must have less than %d interface addresses but has %d addresses\n",
+ ifp->name, OSPF6_MAX_IF_ADDRS_JUMBO, ipv6_count);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ 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;
+}
+
DEFUN (ipv6_ospf6_ifmtu,
ipv6_ospf6_ifmtu_cmd,
"ipv6 ospf6 ifmtu (1-65535)",
@@ -2334,6 +2446,7 @@ static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf)
{
struct ospf6_interface *oi;
struct interface *ifp;
+ char buf[INET_ADDRSTRLEN];
FOR_ALL_INTERFACES (vrf, ifp) {
oi = (struct ospf6_interface *)ifp->info;
@@ -2348,6 +2461,11 @@ static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf)
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);
@@ -2427,7 +2545,9 @@ 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;
}
@@ -2468,6 +2588,9 @@ 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;
}
@@ -2485,6 +2608,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);