]> git.puffer.fish Git - mirror/frr.git/commitdiff
isisd: retrofit the 'net' command
authorEmanuele Di Pascale <emanuele@voltanet.io>
Tue, 13 Nov 2018 16:33:49 +0000 (17:33 +0100)
committerEmanuele Di Pascale <emanuele@voltanet.io>
Tue, 18 Dec 2018 14:21:15 +0000 (15:21 +0100)
This is a simple command but with a complex callback, the only
one in isisd which uses the resource allocation API implemented
in the northbound (i.e. the PREPARE phase).

Signed-off-by: Emanuele Di Pascale <emanuele@voltanet.io>
isisd/isis_cli.c
isisd/isis_cli.h
isisd/isis_northbound.c
isisd/isis_vty_fabricd.c
isisd/isisd.c

index 2650c5bcb79dd3d4d5fa518bed23377ca03b3ffe..41632b0a7575e1661149472de3a64f93f40ef3ae 100644 (file)
@@ -302,6 +302,26 @@ void cli_show_ip_isis_ipv6(struct vty *vty, struct lyd_node *dnode,
                yang_dnode_get_string(dnode, "../area-tag"));
 }
 
+/*
+ * XPath: /frr-isisd:isis/instance/area-address
+ */
+DEFPY(net, net_cmd, "[no] net WORD",
+      "Remove an existing Network Entity Title for this process\n"
+      "A Network Entity Title for this process (OSI only)\n"
+      "XX.XXXX. ... .XXX.XX  Network entity title (NET)\n")
+{
+       nb_cli_enqueue_change(vty, "./area-address",
+                             no ? NB_OP_DELETE : NB_OP_CREATE, net);
+
+       return nb_cli_apply_changes(vty, NULL);
+}
+
+void cli_show_isis_area_address(struct vty *vty, struct lyd_node *dnode,
+                               bool show_defaults)
+{
+       vty_out(vty, " net %s\n", yang_dnode_get_string(dnode, NULL));
+}
+
 void isis_cli_init(void)
 {
        install_element(CONFIG_NODE, &router_isis_cmd);
@@ -310,6 +330,8 @@ void isis_cli_init(void)
        install_element(INTERFACE_NODE, &ip_router_isis_cmd);
        install_element(INTERFACE_NODE, &ip6_router_isis_cmd);
        install_element(INTERFACE_NODE, &no_ip_router_isis_cmd);
+
+       install_element(ISIS_NODE, &net_cmd);
 }
 
 #endif /* ifndef FABRICD */
index e986087595b00326fa1309232528bf83d485b79d..b052f75c274d813b869bfd0b5ae2bafd7c9933ce 100644 (file)
@@ -27,5 +27,7 @@ void cli_show_ip_isis_ipv4(struct vty *vty, struct lyd_node *dnode,
                           bool show_defaults);
 void cli_show_ip_isis_ipv6(struct vty *vty, struct lyd_node *dnode,
                           bool show_defaults);
+void cli_show_isis_area_address(struct vty *vty, struct lyd_node *dnode,
+                               bool show_defaults);
 
 #endif /* ISISD_ISIS_CLI_H_ */
index 71145123457fca1c68442a8387eaf53ae8f4611d..10f8f1e75c5af0e169452a8da954d3c1c4f3aa57 100644 (file)
@@ -113,14 +113,122 @@ static int isis_instance_area_address_create(enum nb_event event,
                                             const struct lyd_node *dnode,
                                             union nb_resource *resource)
 {
-       /* TODO: implement me. */
+       struct isis_area *area;
+       struct area_addr addr, *addrr = NULL, *addrp = NULL;
+       struct listnode *node;
+       uint8_t buff[255];
+       const char *net_title = yang_dnode_get_string(dnode, NULL);
+
+       switch (event) {
+       case NB_EV_VALIDATE:
+               addr.addr_len = dotformat2buff(buff, net_title);
+               memcpy(addr.area_addr, buff, addr.addr_len);
+               if (addr.area_addr[addr.addr_len - 1] != 0) {
+                       flog_warn(
+                               EC_LIB_NB_CB_CONFIG_VALIDATE,
+                               "nsel byte (last byte) in area address must be 0");
+                       return NB_ERR_VALIDATION;
+               }
+               if (isis->sysid_set) {
+                       /* Check that the SystemID portions match */
+                       if (memcmp(isis->sysid, GETSYSID((&addr)),
+                                  ISIS_SYS_ID_LEN)) {
+                               flog_warn(
+                                       EC_LIB_NB_CB_CONFIG_VALIDATE,
+                                       "System ID must not change when defining additional area addresses");
+                               return NB_ERR_VALIDATION;
+                       }
+               }
+               break;
+       case NB_EV_PREPARE:
+               addrr = XMALLOC(MTYPE_ISIS_AREA_ADDR, sizeof(struct area_addr));
+               addrr->addr_len = dotformat2buff(buff, net_title);
+               memcpy(addrr->area_addr, buff, addrr->addr_len);
+               resource->ptr = addrr;
+               break;
+       case NB_EV_ABORT:
+               XFREE(MTYPE_ISIS_AREA_ADDR, resource->ptr);
+               break;
+       case NB_EV_APPLY:
+               area = yang_dnode_get_entry(dnode, true);
+               addrr = resource->ptr;
+
+               if (isis->sysid_set == 0) {
+                       /*
+                        * First area address - get the SystemID for this router
+                        */
+                       memcpy(isis->sysid, GETSYSID(addrr), ISIS_SYS_ID_LEN);
+                       isis->sysid_set = 1;
+               } else {
+                       /* check that we don't already have this address */
+                       for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node,
+                                                 addrp)) {
+                               if ((addrp->addr_len + ISIS_SYS_ID_LEN
+                                    + ISIS_NSEL_LEN)
+                                   != (addrr->addr_len))
+                                       continue;
+                               if (!memcmp(addrp->area_addr, addrr->area_addr,
+                                           addrr->addr_len)) {
+                                       XFREE(MTYPE_ISIS_AREA_ADDR, addrr);
+                                       return NB_OK; /* silent fail */
+                               }
+                       }
+               }
+
+               /*Forget the systemID part of the address */
+               addrr->addr_len -= (ISIS_SYS_ID_LEN + ISIS_NSEL_LEN);
+               assert(area->area_addrs); /* to silence scan-build sillyness */
+               listnode_add(area->area_addrs, addrr);
+
+               /* only now we can safely generate our LSPs for this area */
+               if (listcount(area->area_addrs) > 0) {
+                       if (area->is_type & IS_LEVEL_1)
+                               lsp_generate(area, IS_LEVEL_1);
+                       if (area->is_type & IS_LEVEL_2)
+                               lsp_generate(area, IS_LEVEL_2);
+               }
+               break;
+       }
+
        return NB_OK;
 }
 
 static int isis_instance_area_address_delete(enum nb_event event,
                                             const struct lyd_node *dnode)
 {
-       /* TODO: implement me. */
+       struct area_addr addr, *addrp = NULL;
+       struct listnode *node;
+       uint8_t buff[255];
+       struct isis_area *area;
+       const char *net_title;
+
+       if (event != NB_EV_APPLY)
+               return NB_OK;
+
+       net_title = yang_dnode_get_string(dnode, NULL);
+       addr.addr_len = dotformat2buff(buff, net_title);
+       memcpy(addr.area_addr, buff, (int)addr.addr_len);
+       area = yang_dnode_get_entry(dnode, true);
+       for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node, addrp)) {
+               if ((addrp->addr_len + ISIS_SYS_ID_LEN + 1) == addr.addr_len
+                   && !memcmp(addrp->area_addr, addr.area_addr, addr.addr_len))
+                       break;
+       }
+       if (!addrp)
+               return NB_ERR_INCONSISTENCY;
+
+       listnode_delete(area->area_addrs, addrp);
+       XFREE(MTYPE_ISIS_AREA_ADDR, addrp);
+       /*
+        * Last area address - reset the SystemID for this router
+        */
+       if (listcount(area->area_addrs) == 0) {
+               memset(isis->sysid, 0, ISIS_SYS_ID_LEN);
+               isis->sysid_set = 0;
+               if (isis->debugs & DEBUG_EVENTS)
+                       zlog_debug("Router has no SystemID");
+       }
+
        return NB_OK;
 }
 
@@ -1605,6 +1713,7 @@ const struct frr_yang_module_info frr_isisd_info = {
                        .xpath = "/frr-isisd:isis/instance/area-address",
                        .cbs.create = isis_instance_area_address_create,
                        .cbs.delete = isis_instance_area_address_delete,
+                       .cbs.cli_show = cli_show_isis_area_address,
                },
                {
                        .xpath = "/frr-isisd:isis/instance/dynamic-hostname",
index 819b61dc7ef1478349673de9aff91b96ad47fd9d..e420988f182f918cb31baed3846e9e0ddfaf58d9 100644 (file)
@@ -30,6 +30,7 @@
 #include "isisd/isis_misc.h"
 #include "isisd/isis_lsp.h"
 #include "isisd/isis_csm.h"
+#include "isisd/isis_circuit.h"
 
 DEFUN (fabric_tier,
        fabric_tier_cmd,
index 3721dff3b405164f8fa4168d39135d2c492fbfcb..084cbf16c2520f903517a6c6d4a0cfd4b42d453b 100644 (file)
@@ -1483,6 +1483,7 @@ DEFUN (no_router_openfabric,
        return isis_area_destroy(argv[idx_word]->arg);
 }
 #endif /* ifdef FABRICD */
+#ifdef FABRICD
 /*
  * 'net' command
  */
@@ -1509,7 +1510,7 @@ DEFUN (no_net,
        int idx_word = 2;
        return area_clear_net_title(vty, argv[idx_word]->arg);
 }
-
+#endif /* ifdef FABRICD */
 DEFUN (isis_topology,
        isis_topology_cmd,
        "topology " ISIS_MT_NAMES " [overload]",
@@ -2187,9 +2188,10 @@ void isis_init()
        install_element(CONFIG_NODE, &router_openfabric_cmd);
        install_element(CONFIG_NODE, &no_router_openfabric_cmd);
 #endif /* ifdef FABRICD */
+#ifdef FABRICD
        install_element(ROUTER_NODE, &net_cmd);
        install_element(ROUTER_NODE, &no_net_cmd);
-
+#endif /* ifdef FABRICD */
        install_element(ROUTER_NODE, &isis_topology_cmd);
        install_element(ROUTER_NODE, &no_isis_topology_cmd);