]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/rtadv.c
zebra: Fix tracepoint changes for lttng
[mirror_frr.git] / zebra / rtadv.c
index ca833999cbb708035ffc3daeaa308b69f89f031c..a8ec60844cdaf5fc340caf3053cc79474caba17a 100644 (file)
@@ -51,9 +51,7 @@ static uint32_t interfaces_configured_for_ra_from_bgp;
 
 #if defined(HAVE_RTADV)
 
-#ifndef VTYSH_EXTRACT_PL
 #include "zebra/rtadv_clippy.c"
-#endif
 
 DEFINE_MTYPE_STATIC(ZEBRA, RTADV_PREFIX, "Router Advertisement Prefix");
 DEFINE_MTYPE_STATIC(ZEBRA, ADV_IF, "Advertised Interface");
@@ -73,6 +71,28 @@ DEFINE_MTYPE_STATIC(ZEBRA, ADV_IF, "Advertised Interface");
 #define ALLNODE   "ff02::1"
 #define ALLROUTER "ff02::2"
 
+/* adv list node */
+struct adv_if {
+       char name[INTERFACE_NAMSIZ];
+       struct adv_if_list_item list_item;
+};
+
+static int adv_if_cmp(const struct adv_if *a, const struct adv_if *b)
+{
+       return if_cmp_name_func(a->name, b->name);
+}
+
+DECLARE_SORTLIST_UNIQ(adv_if_list, struct adv_if, list_item, adv_if_cmp);
+
+static int rtadv_prefix_cmp(const struct rtadv_prefix *a,
+                           const struct rtadv_prefix *b)
+{
+       return prefix_cmp(&a->prefix, &b->prefix);
+}
+
+DECLARE_RBTREE_UNIQ(rtadv_prefixes, struct rtadv_prefix, item,
+                   rtadv_prefix_cmp);
+
 DEFINE_MTYPE_STATIC(ZEBRA, RTADV_RDNSS, "Router Advertisement RDNSS");
 DEFINE_MTYPE_STATIC(ZEBRA, RTADV_DNSSL, "Router Advertisement DNSSL");
 
@@ -205,8 +225,7 @@ static void rtadv_send_packet(int sock, struct interface *ifp,
                adata = calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo)));
 
                if (adata == NULL) {
-                       zlog_debug(
-                               "rtadv_send_packet: can't malloc control data");
+                       zlog_debug("%s: can't malloc control data", __func__);
                        exit(-1);
                }
        }
@@ -315,7 +334,7 @@ static void rtadv_send_packet(int sock, struct interface *ifp,
        }
 
        /* Fill in prefix. */
-       for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvPrefixList, node, rprefix)) {
+       frr_each (rtadv_prefixes, zif->rtadv.prefixes, rprefix) {
                struct nd_opt_prefix_info *pinfo;
 
                pinfo = (struct nd_opt_prefix_info *)(buf + len);
@@ -643,8 +662,9 @@ static void rtadv_process_advert(uint8_t *msg, unsigned int len,
             zif->rtadv.lastadvcurhoplimit.tv_sec == 0)) {
                flog_warn(
                        EC_ZEBRA_RA_PARAM_MISMATCH,
-                       "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
-                       ifp->name, ifp->ifindex, addr_str);
+                       "%s(%u): Rx RA - our AdvCurHopLimit (%u) doesn't agree with %s (%u)",
+                       ifp->name, ifp->ifindex, zif->rtadv.AdvCurHopLimit,
+                       addr_str, radvert->nd_ra_curhoplimit);
                monotime(&zif->rtadv.lastadvcurhoplimit);
        }
 
@@ -655,8 +675,11 @@ static void rtadv_process_advert(uint8_t *msg, unsigned int len,
             zif->rtadv.lastadvmanagedflag.tv_sec == 0)) {
                flog_warn(
                        EC_ZEBRA_RA_PARAM_MISMATCH,
-                       "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
-                       ifp->name, ifp->ifindex, addr_str);
+                       "%s(%u): Rx RA - our AdvManagedFlag (%u) doesn't agree with %s (%u)",
+                       ifp->name, ifp->ifindex, zif->rtadv.AdvManagedFlag,
+                       addr_str,
+                       !!CHECK_FLAG(radvert->nd_ra_flags_reserved,
+                                    ND_RA_FLAG_MANAGED));
                monotime(&zif->rtadv.lastadvmanagedflag);
        }
 
@@ -667,8 +690,11 @@ static void rtadv_process_advert(uint8_t *msg, unsigned int len,
             zif->rtadv.lastadvotherconfigflag.tv_sec == 0)) {
                flog_warn(
                        EC_ZEBRA_RA_PARAM_MISMATCH,
-                       "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
-                       ifp->name, ifp->ifindex, addr_str);
+                       "%s(%u): Rx RA - our AdvOtherConfigFlag (%u) doesn't agree with %s (%u)",
+                       ifp->name, ifp->ifindex, zif->rtadv.AdvOtherConfigFlag,
+                       addr_str,
+                       !!CHECK_FLAG(radvert->nd_ra_flags_reserved,
+                                    ND_RA_FLAG_OTHER));
                monotime(&zif->rtadv.lastadvotherconfigflag);
        }
 
@@ -679,20 +705,23 @@ static void rtadv_process_advert(uint8_t *msg, unsigned int len,
             zif->rtadv.lastadvreachabletime.tv_sec == 0)) {
                flog_warn(
                        EC_ZEBRA_RA_PARAM_MISMATCH,
-                       "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
-                       ifp->name, ifp->ifindex, addr_str);
+                       "%s(%u): Rx RA - our AdvReachableTime (%u) doesn't agree with %s (%u)",
+                       ifp->name, ifp->ifindex, zif->rtadv.AdvReachableTime,
+                       addr_str, ntohl(radvert->nd_ra_reachable));
                monotime(&zif->rtadv.lastadvreachabletime);
        }
 
-       if ((ntohl(radvert->nd_ra_retransmit) !=
+       if ((radvert->nd_ra_retransmit && zif->rtadv.AdvRetransTimer) &&
+           (ntohl(radvert->nd_ra_retransmit) !=
             (unsigned int)zif->rtadv.AdvRetransTimer) &&
            (monotime_since(&zif->rtadv.lastadvretranstimer, NULL) >
                     SIXHOUR2USEC ||
             zif->rtadv.lastadvretranstimer.tv_sec == 0)) {
                flog_warn(
                        EC_ZEBRA_RA_PARAM_MISMATCH,
-                       "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
-                       ifp->name, ifp->ifindex, addr_str);
+                       "%s(%u): Rx RA - our AdvRetransTimer (%u) doesn't agree with %s (%u)",
+                       ifp->name, ifp->ifindex, zif->rtadv.AdvRetransTimer,
+                       addr_str, ntohl(radvert->nd_ra_retransmit));
                monotime(&zif->rtadv.lastadvretranstimer);
        }
 
@@ -808,39 +837,51 @@ static int rtadv_make_socket(ns_id_t ns_id)
        int sock = -1;
        int ret = 0;
        struct icmp6_filter filter;
+       int error;
 
        frr_with_privs(&zserv_privs) {
 
                sock = ns_socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6, ns_id);
-
+               /*
+                * with privs might set errno too if it fails save
+                * to the side
+                */
+               error = errno;
        }
 
        if (sock < 0) {
+               zlog_warn("RTADV socket for ns: %u failure to create: %s(%u)",
+                         ns_id, safe_strerror(error), error);
                return -1;
        }
 
        ret = setsockopt_ipv6_pktinfo(sock, 1);
        if (ret < 0) {
+               zlog_warn("RTADV failure to set Packet Information");
                close(sock);
                return ret;
        }
        ret = setsockopt_ipv6_multicast_loop(sock, 0);
        if (ret < 0) {
+               zlog_warn("RTADV failure to set multicast Loop detection");
                close(sock);
                return ret;
        }
        ret = setsockopt_ipv6_unicast_hops(sock, 255);
        if (ret < 0) {
+               zlog_warn("RTADV failure to set maximum unicast hops");
                close(sock);
                return ret;
        }
        ret = setsockopt_ipv6_multicast_hops(sock, 255);
        if (ret < 0) {
+               zlog_warn("RTADV failure to set maximum multicast hops");
                close(sock);
                return ret;
        }
        ret = setsockopt_ipv6_hoplimit(sock, 1);
        if (ret < 0) {
+               zlog_warn("RTADV failure to set maximum incoming hop limit");
                close(sock);
                return ret;
        }
@@ -1065,31 +1106,20 @@ static void rtadv_prefix_free(struct rtadv_prefix *rtadv_prefix)
        XFREE(MTYPE_RTADV_PREFIX, rtadv_prefix);
 }
 
-static struct rtadv_prefix *rtadv_prefix_lookup(struct list *rplist,
-                                               struct prefix_ipv6 *p)
-{
-       struct listnode *node;
-       struct rtadv_prefix *rprefix;
-
-       for (ALL_LIST_ELEMENTS_RO(rplist, node, rprefix))
-               if (prefix_same((struct prefix *)&rprefix->prefix,
-                               (struct prefix *)p))
-                       return rprefix;
-       return NULL;
-}
-
-static struct rtadv_prefix *rtadv_prefix_get(struct list *rplist,
+static struct rtadv_prefix *rtadv_prefix_get(struct rtadv_prefixes_head *list,
                                             struct prefix_ipv6 *p)
 {
-       struct rtadv_prefix *rprefix;
+       struct rtadv_prefix *rprefix, ref;
+
+       ref.prefix = *p;
 
-       rprefix = rtadv_prefix_lookup(rplist, p);
+       rprefix = rtadv_prefixes_find(list, &ref);
        if (rprefix)
                return rprefix;
 
        rprefix = rtadv_prefix_new();
        memcpy(&rprefix->prefix, p, sizeof(struct prefix_ipv6));
-       listnode_add(rplist, rprefix);
+       rtadv_prefixes_add(list, rprefix);
 
        return rprefix;
 }
@@ -1107,7 +1137,7 @@ static void rtadv_prefix_set(struct zebra_if *zif, struct rtadv_prefix *rp)
 {
        struct rtadv_prefix *rprefix;
 
-       rprefix = rtadv_prefix_get(zif->rtadv.AdvPrefixList, &rp->prefix);
+       rprefix = rtadv_prefix_get(zif->rtadv.prefixes, &rp->prefix);
 
        /*
         * Set parameters based on where the prefix is created.
@@ -1142,7 +1172,7 @@ static int rtadv_prefix_reset(struct zebra_if *zif, struct rtadv_prefix *rp)
 {
        struct rtadv_prefix *rprefix;
 
-       rprefix = rtadv_prefix_lookup(zif->rtadv.AdvPrefixList, &rp->prefix);
+       rprefix = rtadv_prefixes_find(zif->rtadv.prefixes, rp);
        if (rprefix != NULL) {
 
                /*
@@ -1165,7 +1195,7 @@ static int rtadv_prefix_reset(struct zebra_if *zif, struct rtadv_prefix *rp)
                        }
                }
 
-               listnode_delete(zif->rtadv.AdvPrefixList, (void *)rprefix);
+               rtadv_prefixes_del(zif->rtadv.prefixes, rprefix);
                rtadv_prefix_free(rprefix);
                return 1;
        } else
@@ -1194,6 +1224,29 @@ void rtadv_delete_prefix(struct zebra_if *zif, const struct prefix *p)
        rtadv_prefix_reset(zif, &rp);
 }
 
+static void rtadv_start_interface_events(struct zebra_vrf *zvrf,
+                                        struct zebra_if *zif)
+{
+       struct adv_if *adv_if = NULL;
+
+       if (zif->ifp->ifindex == IFINDEX_INTERNAL) {
+               if (IS_ZEBRA_DEBUG_EVENT)
+                       zlog_debug(
+                               "%s(%s) has not configured an ifindex yet, delaying until we have one",
+                               zif->ifp->name, zvrf->vrf->name);
+               return;
+       }
+
+       adv_if = adv_if_add(zvrf, zif->ifp->name);
+       if (adv_if != NULL)
+               return; /* Already added */
+
+       if_join_all_router(zvrf->rtadv.sock, zif->ifp);
+
+       if (adv_if_list_count(&zvrf->rtadv.adv_if) == 1)
+               rtadv_event(zvrf, RTADV_START, 0);
+}
+
 static void ipv6_nd_suppress_ra_set(struct interface *ifp,
                                    enum ipv6_nd_suppress_ra_status status)
 {
@@ -1238,14 +1291,7 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp,
                                        RTADV_NUM_FAST_REXMITS;
                        }
 
-                       adv_if = adv_if_add(zvrf, ifp->name);
-                       if (adv_if != NULL)
-                               return; /* Alread added */
-
-                       if_join_all_router(zvrf->rtadv.sock, ifp);
-
-                       if (adv_if_list_count(&zvrf->rtadv.adv_if) == 1)
-                               rtadv_event(zvrf, RTADV_START, 0);
+                       rtadv_start_interface_events(zvrf, zif);
                }
        }
 }
@@ -1358,7 +1404,6 @@ void rtadv_stop_ra_all(void)
 {
        struct vrf *vrf;
        struct interface *ifp;
-       struct listnode *node, *nnode;
        struct zebra_if *zif;
        struct rtadv_prefix *rprefix;
 
@@ -1366,8 +1411,8 @@ void rtadv_stop_ra_all(void)
                FOR_ALL_INTERFACES (vrf, ifp) {
                        zif = ifp->info;
 
-                       for (ALL_LIST_ELEMENTS(zif->rtadv.AdvPrefixList,
-                                              node, nnode, rprefix))
+                       frr_each_safe (rtadv_prefixes, zif->rtadv.prefixes,
+                                      rprefix)
                                rtadv_prefix_reset(zif, rprefix);
 
                        rtadv_stop_ra(ifp);
@@ -2671,7 +2716,7 @@ static int rtadv_config_write(struct vty *vty, struct interface *ifp)
        if (zif->rtadv.AdvLinkMTU)
                vty_out(vty, " ipv6 nd mtu %d\n", zif->rtadv.AdvLinkMTU);
 
-       for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvPrefixList, node, rprefix)) {
+       frr_each (rtadv_prefixes, zif->rtadv.prefixes, rprefix) {
                if ((rprefix->AdvPrefixCreate == PREFIX_SRC_MANUAL)
                    || (rprefix->AdvPrefixCreate == PREFIX_SRC_BOTH)) {
                        vty_out(vty, " ipv6 nd prefix %pFX", &rprefix->prefix);
@@ -2768,6 +2813,81 @@ static void rtadv_event(struct zebra_vrf *zvrf, enum rtadv_event event, int val)
        return;
 }
 
+void rtadv_if_up(struct zebra_if *zif)
+{
+       struct zebra_vrf *zvrf = rtadv_interface_get_zvrf(zif->ifp);
+
+       /* Enable fast tx of RA if enabled && RA interval is not in msecs */
+       if (zif->rtadv.AdvSendAdvertisements &&
+           (zif->rtadv.MaxRtrAdvInterval >= 1000) &&
+           zif->rtadv.UseFastRexmit) {
+               zif->rtadv.inFastRexmit = 1;
+               zif->rtadv.NumFastReXmitsRemain = RTADV_NUM_FAST_REXMITS;
+       }
+
+       /*
+        * startup the state machine, if it hasn't been already
+        * due to a delayed ifindex on startup ordering
+        */
+       if (zif->rtadv.AdvSendAdvertisements)
+               rtadv_start_interface_events(zvrf, zif);
+}
+
+void rtadv_if_init(struct zebra_if *zif)
+{
+       /* Set default router advertise values. */
+       struct rtadvconf *rtadv;
+
+       rtadv = &zif->rtadv;
+
+       rtadv->AdvSendAdvertisements = 0;
+       rtadv->MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
+       rtadv->MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
+       rtadv->AdvIntervalTimer = 0;
+       rtadv->AdvManagedFlag = 0;
+       rtadv->AdvOtherConfigFlag = 0;
+       rtadv->AdvHomeAgentFlag = 0;
+       rtadv->AdvLinkMTU = 0;
+       rtadv->AdvReachableTime = 0;
+       rtadv->AdvRetransTimer = 0;
+       rtadv->AdvCurHopLimit = RTADV_DEFAULT_HOPLIMIT;
+       memset(&rtadv->lastadvcurhoplimit, 0,
+              sizeof(rtadv->lastadvcurhoplimit));
+       memset(&rtadv->lastadvmanagedflag, 0,
+              sizeof(rtadv->lastadvmanagedflag));
+       memset(&rtadv->lastadvotherconfigflag, 0,
+              sizeof(rtadv->lastadvotherconfigflag));
+       memset(&rtadv->lastadvreachabletime, 0,
+              sizeof(rtadv->lastadvreachabletime));
+       memset(&rtadv->lastadvretranstimer, 0,
+              sizeof(rtadv->lastadvretranstimer));
+       rtadv->AdvDefaultLifetime = -1; /* derive from MaxRtrAdvInterval */
+       rtadv->HomeAgentPreference = 0;
+       rtadv->HomeAgentLifetime = -1; /* derive from AdvDefaultLifetime */
+       rtadv->AdvIntervalOption = 0;
+       rtadv->UseFastRexmit = true;
+       rtadv->DefaultPreference = RTADV_PREF_MEDIUM;
+
+       rtadv_prefixes_init(rtadv->prefixes);
+
+       rtadv->AdvRDNSSList = list_new();
+       rtadv->AdvDNSSLList = list_new();
+}
+
+void rtadv_if_fini(struct zebra_if *zif)
+{
+       struct rtadvconf *rtadv;
+       struct rtadv_prefix *rp;
+
+       rtadv = &zif->rtadv;
+
+       while ((rp = rtadv_prefixes_pop(rtadv->prefixes)))
+               rtadv_prefix_free(rp);
+
+       list_delete(&rtadv->AdvRDNSSList);
+       list_delete(&rtadv->AdvDNSSLList);
+}
+
 void rtadv_vrf_init(struct zebra_vrf *zvrf)
 {
        if (!vrf_is_backend_netns() && (zvrf_id(zvrf) != VRF_DEFAULT))
@@ -2847,7 +2967,7 @@ static int if_join_all_router(int sock, struct interface *ifp)
 
        struct ipv6_mreq mreq;
 
-       memset(&mreq, 0, sizeof(struct ipv6_mreq));
+       memset(&mreq, 0, sizeof(mreq));
        inet_pton(AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
        mreq.ipv6mr_interface = ifp->ifindex;
 
@@ -2873,7 +2993,7 @@ static int if_leave_all_router(int sock, struct interface *ifp)
 
        struct ipv6_mreq mreq;
 
-       memset(&mreq, 0, sizeof(struct ipv6_mreq));
+       memset(&mreq, 0, sizeof(mreq));
        inet_pton(AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
        mreq.ipv6mr_interface = ifp->ifindex;
 
@@ -2899,37 +3019,7 @@ bool rtadv_compiled_in(void)
        return true;
 }
 
-#else
-void rtadv_vrf_init(struct zebra_vrf *zvrf)
-{
-       /* Empty.*/;
-}
-
-void rtadv_cmd_init(void)
-{
-       /* Empty.*/;
-}
-
-void rtadv_add_prefix(struct zebra_if *zif, const struct prefix_ipv6 *p)
-{
-       /* Empty.*/;
-}
-
-void rtadv_delete_prefix(struct zebra_if *zif, const struct prefix *p)
-{
-       /* Empty.*/;
-}
-
-void rtadv_stop_ra(struct interface *ifp)
-{
-       /* Empty.*/;
-}
-
-void rtadv_stop_ra_all(void)
-{
-       /* Empty.*/;
-}
-
+#else /* !HAVE_RTADV */
 /*
  * If the end user does not have RADV enabled we should
  * handle this better