]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/irdp_interface.c
isisd: implement the 'lsp-too-large' notification
[mirror_frr.git] / zebra / irdp_interface.c
index 84165dee6145e388de193ff7b7b041fdfc6ab227..3e50550dd2f8dcd9a541bff34baee9c147f0f9e6 100644 (file)
@@ -1,7 +1,13 @@
 /*
  *
- * Copyright (C) 2000  Robert Olsson.
- * Swedish University of Agricultural Sciences
+ * Copyright (C) 1997, 2000
+ * Portions:
+ *   Swedish University of Agricultural Sciences
+ *   Robert Olsson
+ *   Kunihiro Ishiguro
+ *
+ * Thanks to Jens Laas at Swedish University of Agricultural Sciences
+ * for reviewing and tests.
  *
  * This file is part of GNU Zebra.
  *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING.  If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- */
-
-/*
- * This work includes work with the following copywrite:
- *
- * Copyright (C) 1997, 2000 Kunihiro Ishiguro
- *
- */
-
-/*
- * Thanks to Jens Låås at Swedish University of Agricultural Sciences
- * for reviewing and tests.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-
 #include <zebra.h>
 
-#ifdef HAVE_IRDP
-
 #include "if.h"
 #include "vty.h"
 #include "sockunion.h"
 #include "log.h"
 #include "zclient.h"
 #include "thread.h"
+#include "lib_errors.h"
 #include "zebra/interface.h"
 #include "zebra/rtadv.h"
 #include "zebra/rib.h"
 #include "zebra/zserv.h"
 #include "zebra/redistribute.h"
 #include "zebra/irdp.h"
+#include "zebra/zebra_errors.h"
 #include <netinet/ip_icmp.h>
 #include "if.h"
 #include "sockunion.h"
 
 extern int irdp_sock;
 
-static const char *inet_2a(u_int32_t a, char *b)
+DEFINE_MTYPE_STATIC(ZEBRA, IRDP_IF, "IRDP interface data")
+
+#define IRDP_CONFIGED                                                                 \
+       do {                                                                          \
+               if (!irdp) {                                                          \
+                       vty_out(vty,                                                  \
+                               "Please Configure IRDP before using this command\n"); \
+                       return CMD_WARNING_CONFIG_FAILED;                             \
+               }                                                                     \
+       } while (0)
+
+static struct irdp_interface *irdp_if_get(struct interface *ifp)
+{
+       struct zebra_if *zi = ifp->info;
+
+       if (!zi)
+               return NULL;
+
+       if (!zi->irdp)
+               zi->irdp = XCALLOC(MTYPE_IRDP_IF, sizeof(*zi->irdp));
+
+       if (!zi->irdp->started)
+               return NULL;
+
+       return zi->irdp;
+}
+
+static int irdp_if_delete(struct interface *ifp)
+{
+       struct zebra_if *zi = ifp->info;
+       if (!zi)
+               return 0;
+       XFREE(MTYPE_IRDP_IF, zi->irdp);
+       return 0;
+}
+
+static const char *inet_2a(uint32_t a, char *b)
 {
        sprintf(b, "%u.%u.%u.%u", (a)&0xFF, (a >> 8) & 0xFF, (a >> 16) & 0xFF,
                (a >> 24) & 0xFF);
@@ -85,7 +113,7 @@ static struct prefix *irdp_get_prefix(struct interface *ifp)
 }
 
 /* Join to the add/leave multicast group. */
-static int if_group(struct interface *ifp, int sock, u_int32_t group,
+static int if_group(struct interface *ifp, int sock, uint32_t group,
                    int add_leave)
 {
        struct ip_mreq m;
@@ -98,7 +126,8 @@ static int if_group(struct interface *ifp, int sock, u_int32_t group,
        p = irdp_get_prefix(ifp);
 
        if (!p) {
-               zlog_warn("IRDP: can't get address for %s", ifp->name);
+               flog_warn(EC_ZEBRA_NO_IFACE_ADDR,
+                         "IRDP: can't get address for %s", ifp->name);
                return 1;
        }
 
@@ -107,10 +136,10 @@ static int if_group(struct interface *ifp, int sock, u_int32_t group,
        ret = setsockopt(sock, IPPROTO_IP, add_leave, (char *)&m,
                         sizeof(struct ip_mreq));
        if (ret < 0)
-               zlog_warn("IRDP: %s can't setsockopt %s: %s",
-                         add_leave == IP_ADD_MEMBERSHIP ? "join group"
-                                                        : "leave group",
-                         inet_2a(group, b1), safe_strerror(errno));
+               flog_err_sys(EC_LIB_SOCKET, "IRDP: %s can't setsockopt %s: %s",
+                            add_leave == IP_ADD_MEMBERSHIP ? "join group"
+                                                           : "leave group",
+                            inet_2a(group, b1), safe_strerror(errno));
 
        return ret;
 }
@@ -118,10 +147,13 @@ static int if_group(struct interface *ifp, int sock, u_int32_t group,
 static int if_add_group(struct interface *ifp)
 {
        struct zebra_if *zi = ifp->info;
-       struct irdp_interface *irdp = &zi->irdp;
+       struct irdp_interface *irdp = zi->irdp;
        int ret;
        char b1[INET_ADDRSTRLEN];
 
+       if (!irdp)
+               return -1;
+
        ret = if_group(ifp, irdp_sock, INADDR_ALLRTRS_GROUP, IP_ADD_MEMBERSHIP);
        if (ret < 0) {
                return ret;
@@ -136,10 +168,13 @@ static int if_add_group(struct interface *ifp)
 static int if_drop_group(struct interface *ifp)
 {
        struct zebra_if *zi = ifp->info;
-       struct irdp_interface *irdp = &zi->irdp;
+       struct irdp_interface *irdp = zi->irdp;
        int ret;
        char b1[INET_ADDRSTRLEN];
 
+       if (!irdp)
+               return -1;
+
        ret = if_group(ifp, irdp_sock, INADDR_ALLRTRS_GROUP,
                       IP_DROP_MEMBERSHIP);
        if (ret < 0)
@@ -151,11 +186,8 @@ static int if_drop_group(struct interface *ifp)
        return 0;
 }
 
-static void if_set_defaults(struct interface *ifp)
+static void if_set_defaults(struct irdp_interface *irdp)
 {
-       struct zebra_if *zi = ifp->info;
-       struct irdp_interface *irdp = &zi->irdp;
-
        irdp->MaxAdvertInterval = IRDP_MAXADVERTINTERVAL;
        irdp->MinAdvertInterval = IRDP_MINADVERTINTERVAL;
        irdp->Preference = IRDP_PREFERENCE;
@@ -177,20 +209,23 @@ static void irdp_if_start(struct interface *ifp, int multicast,
                          int set_defaults)
 {
        struct zebra_if *zi = ifp->info;
-       struct irdp_interface *irdp = &zi->irdp;
+       struct irdp_interface *irdp = zi->irdp;
        struct listnode *node;
        struct connected *ifc;
-       u_int32_t timer, seed;
+       uint32_t timer, seed;
 
+       assert(irdp);
+
+       irdp->started = true;
        if (irdp->flags & IF_ACTIVE) {
-               zlog_warn("IRDP: Interface is already active %s", ifp->name);
+               zlog_debug("IRDP: Interface is already active %s", ifp->name);
                return;
        }
        if ((irdp_sock < 0) && ((irdp_sock = irdp_sock_init()) < 0)) {
-               zlog_warn(
-                       "IRDP: Cannot activate interface %s (cannot create "
-                       "IRDP socket)",
-                       ifp->name);
+               flog_warn(EC_ZEBRA_IRDP_CANNOT_ACTIVATE_IFACE,
+                         "IRDP: Cannot activate interface %s (cannot create "
+                         "IRDP socket)",
+                         ifp->name);
                return;
        }
        irdp->flags |= IF_ACTIVE;
@@ -201,7 +236,8 @@ static void irdp_if_start(struct interface *ifp, int multicast,
        if_add_update(ifp);
 
        if (!(ifp->flags & IFF_UP)) {
-               zlog_warn("IRDP: Interface is down %s", ifp->name);
+               flog_warn(EC_ZEBRA_IRDP_IFACE_DOWN,
+                         "IRDP: Interface is down %s", ifp->name);
        }
 
        /* Shall we cancel if_start if if_add_group fails? */
@@ -210,13 +246,14 @@ static void irdp_if_start(struct interface *ifp, int multicast,
                if_add_group(ifp);
 
                if (!(ifp->flags & (IFF_MULTICAST | IFF_ALLMULTI))) {
-                       zlog_warn("IRDP: Interface not multicast enabled %s",
+                       flog_warn(EC_ZEBRA_IRDP_IFACE_MCAST_DISABLED,
+                                 "IRDP: Interface not multicast enabled %s",
                                  ifp->name);
                }
        }
 
        if (set_defaults)
-               if_set_defaults(ifp);
+               if_set_defaults(irdp);
 
        irdp->irdp_sent = 0;
 
@@ -247,22 +284,23 @@ static void irdp_if_start(struct interface *ifp, int multicast,
                zlog_debug("IRDP: Init timer for %s set to %u", ifp->name,
                           timer);
 
-       irdp->t_advertise =
-               thread_add_timer(zebrad.master, irdp_send_thread, ifp, timer);
+       irdp->t_advertise = NULL;
+       thread_add_timer(zebrad.master, irdp_send_thread, ifp, timer,
+                        &irdp->t_advertise);
 }
 
 static void irdp_if_stop(struct interface *ifp)
 {
        struct zebra_if *zi = ifp->info;
-       struct irdp_interface *irdp = &zi->irdp;
+       struct irdp_interface *irdp = zi->irdp;
 
        if (irdp == NULL) {
-               zlog_warn("Interface %s structure is NULL", ifp->name);
+               zlog_debug("Interface %s structure is NULL", ifp->name);
                return;
        }
 
        if (!(irdp->flags & IF_ACTIVE)) {
-               zlog_warn("Interface is not active %s", ifp->name);
+               zlog_debug("Interface is not active %s", ifp->name);
                return;
        }
 
@@ -271,8 +309,7 @@ static void irdp_if_stop(struct interface *ifp)
 
        irdp_advert_off(ifp);
 
-       list_delete(irdp->AdvPrefList);
-       irdp->AdvPrefList = NULL;
+       list_delete(&irdp->AdvPrefList);
 
        irdp->flags = 0;
 }
@@ -281,10 +318,13 @@ static void irdp_if_stop(struct interface *ifp)
 static void irdp_if_shutdown(struct interface *ifp)
 {
        struct zebra_if *zi = ifp->info;
-       struct irdp_interface *irdp = &zi->irdp;
+       struct irdp_interface *irdp = zi->irdp;
+
+       if (!irdp)
+               return;
 
        if (irdp->flags & IF_SHUTDOWN) {
-               zlog_warn("IRDP: Interface is already shutdown %s", ifp->name);
+               zlog_debug("IRDP: Interface is already shutdown %s", ifp->name);
                return;
        }
 
@@ -300,11 +340,13 @@ static void irdp_if_shutdown(struct interface *ifp)
 
 static void irdp_if_no_shutdown(struct interface *ifp)
 {
-       struct zebra_if *zi = ifp->info;
-       struct irdp_interface *irdp = &zi->irdp;
+       struct irdp_interface *irdp = irdp_if_get(ifp);
+
+       if (!irdp)
+               return;
 
        if (!(irdp->flags & IF_SHUTDOWN)) {
-               zlog_warn("IRDP: Interface is not shutdown %s", ifp->name);
+               zlog_debug("IRDP: Interface is not shutdown %s", ifp->name);
                return;
        }
 
@@ -316,41 +358,42 @@ static void irdp_if_no_shutdown(struct interface *ifp)
 
 /* Write configuration to user */
 
-void irdp_config_write(struct vty *vty, struct interface *ifp)
+int irdp_config_write(struct vty *vty, struct interface *ifp)
 {
        struct zebra_if *zi = ifp->info;
-       struct irdp_interface *irdp = &zi->irdp;
+       struct irdp_interface *irdp = zi->irdp;
        struct Adv *adv;
        struct listnode *node;
        char b1[INET_ADDRSTRLEN];
 
+       if (!irdp)
+               return 0;
+
        if (irdp->flags & IF_ACTIVE || irdp->flags & IF_SHUTDOWN) {
 
                if (irdp->flags & IF_SHUTDOWN)
-                       vty_out(vty, " ip irdp shutdown %s", VTY_NEWLINE);
+                       vty_out(vty, " ip irdp shutdown \n");
 
                if (irdp->flags & IF_BROADCAST)
-                       vty_out(vty, " ip irdp broadcast%s", VTY_NEWLINE);
+                       vty_out(vty, " ip irdp broadcast\n");
                else
-                       vty_out(vty, " ip irdp multicast%s", VTY_NEWLINE);
+                       vty_out(vty, " ip irdp multicast\n");
 
-               vty_out(vty, " ip irdp preference %ld%s", irdp->Preference,
-                       VTY_NEWLINE);
+               vty_out(vty, " ip irdp preference %ld\n", irdp->Preference);
 
                for (ALL_LIST_ELEMENTS_RO(irdp->AdvPrefList, node, adv))
-                       vty_out(vty, " ip irdp address %s preference %d%s",
-                               inet_2a(adv->ip.s_addr, b1), adv->pref,
-                               VTY_NEWLINE);
+                       vty_out(vty, " ip irdp address %s preference %d\n",
+                               inet_2a(adv->ip.s_addr, b1), adv->pref);
 
-               vty_out(vty, " ip irdp holdtime %d%s", irdp->Lifetime,
-                       VTY_NEWLINE);
+               vty_out(vty, " ip irdp holdtime %d\n", irdp->Lifetime);
 
-               vty_out(vty, " ip irdp minadvertinterval %ld%s",
-                       irdp->MinAdvertInterval, VTY_NEWLINE);
+               vty_out(vty, " ip irdp minadvertinterval %ld\n",
+                       irdp->MinAdvertInterval);
 
-               vty_out(vty, " ip irdp maxadvertinterval %ld%s",
-                       irdp->MaxAdvertInterval, VTY_NEWLINE);
+               vty_out(vty, " ip irdp maxadvertinterval %ld\n",
+                       irdp->MaxAdvertInterval);
        }
+       return 0;
 }
 
 
@@ -362,6 +405,7 @@ DEFUN (ip_irdp_multicast,
        "Use multicast mode\n")
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
+       irdp_if_get(ifp);
 
        irdp_if_start(ifp, TRUE, TRUE);
        return CMD_SUCCESS;
@@ -375,6 +419,7 @@ DEFUN (ip_irdp_broadcast,
        "Use broadcast mode\n")
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
+       irdp_if_get(ifp);
 
        irdp_if_start(ifp, FALSE, TRUE);
        return CMD_SUCCESS;
@@ -430,11 +475,9 @@ DEFUN (ip_irdp_holdtime,
 {
        int idx_number = 3;
        VTY_DECLVAR_CONTEXT(interface, ifp);
-       struct zebra_if *zi;
-       struct irdp_interface *irdp;
+       struct irdp_interface *irdp = irdp_if_get(ifp);
 
-       zi = ifp->info;
-       irdp = &zi->irdp;
+       IRDP_CONFIGED;
 
        irdp->Lifetime = atoi(argv[idx_number]->arg);
        return CMD_SUCCESS;
@@ -450,11 +493,9 @@ DEFUN (ip_irdp_minadvertinterval,
 {
        int idx_number = 3;
        VTY_DECLVAR_CONTEXT(interface, ifp);
-       struct zebra_if *zi;
-       struct irdp_interface *irdp;
+       struct irdp_interface *irdp = irdp_if_get(ifp);
 
-       zi = ifp->info;
-       irdp = &zi->irdp;
+       IRDP_CONFIGED;
 
        if ((unsigned)atoi(argv[idx_number]->arg) <= irdp->MaxAdvertInterval) {
                irdp->MinAdvertInterval = atoi(argv[idx_number]->arg);
@@ -462,9 +503,8 @@ DEFUN (ip_irdp_minadvertinterval,
        } else {
                vty_out(vty,
                        "%% MinAdvertInterval must be less than or equal to "
-                       "MaxAdvertInterval%s",
-                       VTY_NEWLINE);
-               return CMD_WARNING;
+                       "MaxAdvertInterval\n");
+               return CMD_WARNING_CONFIG_FAILED;
        }
 }
 
@@ -478,11 +518,9 @@ DEFUN (ip_irdp_maxadvertinterval,
 {
        int idx_number = 3;
        VTY_DECLVAR_CONTEXT(interface, ifp);
-       struct zebra_if *zi;
-       struct irdp_interface *irdp;
+       struct irdp_interface *irdp = irdp_if_get(ifp);
 
-       zi = ifp->info;
-       irdp = &zi->irdp;
+       IRDP_CONFIGED;
 
        if (irdp->MinAdvertInterval <= (unsigned)atoi(argv[idx_number]->arg)) {
                irdp->MaxAdvertInterval = atoi(argv[idx_number]->arg);
@@ -490,9 +528,8 @@ DEFUN (ip_irdp_maxadvertinterval,
        } else {
                vty_out(vty,
                        "%% MaxAdvertInterval must be greater than or equal to "
-                       "MinAdvertInterval%s",
-                       VTY_NEWLINE);
-               return CMD_WARNING;
+                       "MinAdvertInterval\n");
+               return CMD_WARNING_CONFIG_FAILED;
        }
 }
 
@@ -511,11 +548,9 @@ DEFUN (ip_irdp_preference,
 {
        int idx_number = 3;
        VTY_DECLVAR_CONTEXT(interface, ifp);
-       struct zebra_if *zi;
-       struct irdp_interface *irdp;
+       struct irdp_interface *irdp = irdp_if_get(ifp);
 
-       zi = ifp->info;
-       irdp = &zi->irdp;
+       IRDP_CONFIGED;
 
        irdp->Preference = atoi(argv[idx_number]->arg);
        return CMD_SUCCESS;
@@ -534,20 +569,18 @@ DEFUN (ip_irdp_address_preference,
        int idx_ipv4 = 3;
        int idx_number = 5;
        VTY_DECLVAR_CONTEXT(interface, ifp);
+       struct irdp_interface *irdp = irdp_if_get(ifp);
        struct listnode *node;
        struct in_addr ip;
        int pref;
        int ret;
-       struct zebra_if *zi;
-       struct irdp_interface *irdp;
        struct Adv *adv;
 
-       zi = ifp->info;
-       irdp = &zi->irdp;
+       IRDP_CONFIGED;
 
        ret = inet_aton(argv[idx_ipv4]->arg, &ip);
        if (!ret)
-               return CMD_WARNING;
+               return CMD_WARNING_CONFIG_FAILED;
 
        pref = atoi(argv[idx_number]->arg);
 
@@ -576,19 +609,17 @@ DEFUN (no_ip_irdp_address_preference,
 {
        int idx_ipv4 = 4;
        VTY_DECLVAR_CONTEXT(interface, ifp);
+       struct irdp_interface *irdp = irdp_if_get(ifp);
        struct listnode *node, *nnode;
        struct in_addr ip;
        int ret;
-       struct zebra_if *zi;
-       struct irdp_interface *irdp;
        struct Adv *adv;
 
-       zi = ifp->info;
-       irdp = &zi->irdp;
+       IRDP_CONFIGED;
 
        ret = inet_aton(argv[idx_ipv4]->arg, &ip);
        if (!ret)
-               return CMD_WARNING;
+               return CMD_WARNING_CONFIG_FAILED;
 
        for (ALL_LIST_ELEMENTS(irdp->AdvPrefList, node, nnode, adv)) {
                if (adv->ip.s_addr == ip.s_addr) {
@@ -609,11 +640,9 @@ DEFUN (ip_irdp_debug_messages,
        "Enable debugging for IRDP messages\n")
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
-       struct zebra_if *zi;
-       struct irdp_interface *irdp;
+       struct irdp_interface *irdp = irdp_if_get(ifp);
 
-       zi = ifp->info;
-       irdp = &zi->irdp;
+       IRDP_CONFIGED;
 
        irdp->flags |= IF_DEBUG_MESSAGES;
 
@@ -629,11 +658,9 @@ DEFUN (ip_irdp_debug_misc,
        "Enable debugging for miscellaneous IRDP events\n")
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
-       struct zebra_if *zi;
-       struct irdp_interface *irdp;
+       struct irdp_interface *irdp = irdp_if_get(ifp);
 
-       zi = ifp->info;
-       irdp = &zi->irdp;
+       IRDP_CONFIGED;
 
        irdp->flags |= IF_DEBUG_MISC;
 
@@ -649,11 +676,9 @@ DEFUN (ip_irdp_debug_packet,
        "Enable debugging for IRDP packets\n")
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
-       struct zebra_if *zi;
-       struct irdp_interface *irdp;
+       struct irdp_interface *irdp = irdp_if_get(ifp);
 
-       zi = ifp->info;
-       irdp = &zi->irdp;
+       IRDP_CONFIGED;
 
        irdp->flags |= IF_DEBUG_PACKET;
 
@@ -670,11 +695,9 @@ DEFUN (ip_irdp_debug_disable,
        "Disable debugging for all IRDP events\n")
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
-       struct zebra_if *zi;
-       struct irdp_interface *irdp;
+       struct irdp_interface *irdp = irdp_if_get(ifp);
 
-       zi = ifp->info;
-       irdp = &zi->irdp;
+       IRDP_CONFIGED;
 
        irdp->flags &= ~IF_DEBUG_PACKET;
        irdp->flags &= ~IF_DEBUG_MESSAGES;
@@ -683,8 +706,11 @@ DEFUN (ip_irdp_debug_disable,
        return CMD_SUCCESS;
 }
 
-void irdp_init()
+void irdp_if_init()
 {
+       hook_register(zebra_if_config_wr, irdp_config_write);
+       hook_register(if_del, irdp_if_delete);
+
        install_element(INTERFACE_NODE, &ip_irdp_broadcast_cmd);
        install_element(INTERFACE_NODE, &ip_irdp_multicast_cmd);
        install_element(INTERFACE_NODE, &no_ip_irdp_cmd);
@@ -702,5 +728,3 @@ void irdp_init()
        install_element(INTERFACE_NODE, &ip_irdp_debug_packet_cmd);
        install_element(INTERFACE_NODE, &ip_irdp_debug_disable_cmd);
 }
-
-#endif /* HAVE_IRDP */