]> git.proxmox.com Git - mirror_frr.git/blobdiff - vrrpd/vrrp.c
Merge pull request #5793 from ton31337/fix/formatting_show_bgp_summary_failed
[mirror_frr.git] / vrrpd / vrrp.c
index 42bb154f985e988c96d5d1e89ddd9d571a41caaa..03a08dd86b41ac43be9066c93c64569191918661 100644 (file)
@@ -211,7 +211,16 @@ static struct vrrp_vrouter *vrrp_lookup_by_if_mvl(struct interface *mvl_ifp)
                return NULL;
        }
 
-       p = if_lookup_by_index(mvl_ifp->link_ifindex, VRF_DEFAULT);
+       p = if_lookup_by_index(mvl_ifp->link_ifindex, mvl_ifp->vrf_id);
+
+       if (!p) {
+               DEBUGD(&vrrp_dbg_zebra,
+                      VRRP_LOGPFX
+                      "Tried to lookup interface %d, parent of %s, but it doesn't exist",
+                      mvl_ifp->link_ifindex, mvl_ifp->name);
+               return NULL;
+       }
+
        uint8_t vrid = mvl_ifp->hw_addr[5];
 
        return vrrp_lookup(p, vrid);
@@ -397,9 +406,10 @@ static bool vrrp_has_ip(struct vrrp_vrouter *vr, struct ipaddr *ip)
        return false;
 }
 
-int vrrp_add_ip(struct vrrp_router *r, struct ipaddr *ip)
+int vrrp_add_ip(struct vrrp_vrouter *vr, struct ipaddr *ip)
 {
-       int af = (ip->ipa_type == IPADDR_V6) ? AF_INET6 : AF_INET;
+       struct vrrp_router *r = IS_IPADDR_V4(ip) ? vr->v4 : vr->v6;
+       int af = r->family;
 
        assert(r->family == af);
        assert(!(r->vr->version == 2 && ip->ipa_type == IPADDR_V6));
@@ -443,7 +453,7 @@ int vrrp_add_ipv4(struct vrrp_vrouter *vr, struct in_addr v4)
 
        ip.ipa_type = IPADDR_V4;
        ip.ipaddr_v4 = v4;
-       return vrrp_add_ip(vr->v4, &ip);
+       return vrrp_add_ip(vr, &ip);
 }
 
 int vrrp_add_ipv6(struct vrrp_vrouter *vr, struct in6_addr v6)
@@ -454,15 +464,17 @@ int vrrp_add_ipv6(struct vrrp_vrouter *vr, struct in6_addr v6)
 
        ip.ipa_type = IPADDR_V6;
        ip.ipaddr_v6 = v6;
-       return vrrp_add_ip(vr->v6, &ip);
+       return vrrp_add_ip(vr, &ip);
 }
 
-int vrrp_del_ip(struct vrrp_router *r, struct ipaddr *ip)
+int vrrp_del_ip(struct vrrp_vrouter *vr, struct ipaddr *ip)
 {
        struct listnode *ln, *nn;
        struct ipaddr *iter;
        int ret = 0;
 
+       struct vrrp_router *r = IS_IPADDR_V4(ip) ? vr->v4 : vr->v6;
+
        if (!vrrp_has_ip(r->vr, ip))
                return 0;
 
@@ -488,7 +500,7 @@ int vrrp_del_ipv6(struct vrrp_vrouter *vr, struct in6_addr v6)
 
        ip.ipa_type = IPADDR_V6;
        ip.ipaddr_v6 = v6;
-       return vrrp_del_ip(vr->v6, &ip);
+       return vrrp_del_ip(vr, &ip);
 }
 
 int vrrp_del_ipv4(struct vrrp_vrouter *vr, struct in_addr v4)
@@ -497,7 +509,7 @@ int vrrp_del_ipv4(struct vrrp_vrouter *vr, struct in_addr v4)
 
        ip.ipa_type = IPADDR_V4;
        ip.ipaddr_v4 = v4;
-       return vrrp_del_ip(vr->v4, &ip);
+       return vrrp_del_ip(vr, &ip);
 }
 
 
@@ -525,8 +537,9 @@ static bool vrrp_attach_interface(struct vrrp_router *r)
        /* Search for existing interface with computed MAC address */
        struct interface **ifps;
 
-       size_t ifps_cnt = if_lookup_by_hwaddr(
-               r->vmac.octet, sizeof(r->vmac.octet), &ifps, VRF_DEFAULT);
+       size_t ifps_cnt =
+               if_lookup_by_hwaddr(r->vmac.octet, sizeof(r->vmac.octet), &ifps,
+                                   r->vr->ifp->vrf_id);
 
        /*
         * Filter to only those macvlan interfaces whose parent is the base
@@ -649,12 +662,12 @@ void vrrp_vrouter_destroy(struct vrrp_vrouter *vr)
        XFREE(MTYPE_VRRP_RTR, vr);
 }
 
-struct vrrp_vrouter *vrrp_lookup(struct interface *ifp, uint8_t vrid)
+struct vrrp_vrouter *vrrp_lookup(const struct interface *ifp, uint8_t vrid)
 {
        struct vrrp_vrouter vr;
 
        vr.vrid = vrid;
-       vr.ifp = ifp;
+       vr.ifp = (struct interface *)ifp;
 
        return hash_lookup(vrrp_vrouters_hash, &vr);
 }
@@ -1048,6 +1061,8 @@ done:
  *
  * This function:
  * - Creates two sockets, one for Tx, one for Rx
+ * - Binds the Tx socket to the macvlan device, if necessary (VRF case)
+ * - Binds the Rx socket to the base interface
  * - Joins the Rx socket to the appropriate VRRP multicast group
  * - Sets the Tx socket to set the TTL (v4) or Hop Limit (v6) field to 255 for
  *   all transmitted IPvX packets
@@ -1074,8 +1089,10 @@ static int vrrp_socket(struct vrrp_router *r)
        bool failed = false;
 
        frr_with_privs(&vrrp_privs) {
-               r->sock_rx = socket(r->family, SOCK_RAW, IPPROTO_VRRP);
-               r->sock_tx = socket(r->family, SOCK_RAW, IPPROTO_VRRP);
+               r->sock_rx = vrf_socket(r->family, SOCK_RAW, IPPROTO_VRRP,
+                                       r->vr->ifp->vrf_id, NULL);
+               r->sock_tx = vrf_socket(r->family, SOCK_RAW, IPPROTO_VRRP,
+                                       r->vr->ifp->vrf_id, NULL);
        }
 
        if (r->sock_rx < 0 || r->sock_tx < 0) {
@@ -1088,6 +1105,27 @@ static int vrrp_socket(struct vrrp_router *r)
                goto done;
        }
 
+       /*
+        * Bind Tx socket to macvlan device - necessary for VRF support,
+        * otherwise the kernel will select the vrf device
+        */
+       if (r->vr->ifp->vrf_id != VRF_DEFAULT) {
+               frr_with_privs (&vrrp_privs) {
+                       ret = setsockopt(r->sock_tx, SOL_SOCKET,
+                                        SO_BINDTODEVICE, r->mvl_ifp->name,
+                                        strlen(r->mvl_ifp->name));
+               }
+
+               if (ret < 0) {
+                       zlog_warn(
+                               VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
+                               "Failed to bind Tx socket to macvlan device '%s'",
+                               r->vr->vrid, family2str(r->family),
+                               r->mvl_ifp->name);
+                       failed = true;
+                       goto done;
+               }
+       }
        /* Configure sockets */
        if (r->family == AF_INET) {
                /* Set Tx socket to always Tx with TTL set to 255 */
@@ -1410,7 +1448,7 @@ static void vrrp_change_state_initialize(struct vrrp_router *r)
        r->ndisc_pending = false;
 
        /* Disable ND Router Advertisements */
-       if (r->family == AF_INET6)
+       if (r->family == AF_INET6 && r->mvl_ifp)
                vrrp_zebra_radv_set(r, false);
 }
 
@@ -1618,7 +1656,8 @@ static int vrrp_shutdown(struct vrrp_router *r)
        THREAD_OFF(r->t_write);
 
        /* Protodown macvlan */
-       vrrp_zclient_send_interface_protodown(r->mvl_ifp, true);
+       if (r->mvl_ifp)
+               vrrp_zclient_send_interface_protodown(r->mvl_ifp, true);
 
        /* Throw away our source address */
        memset(&r->src, 0x00, sizeof(r->src));
@@ -1722,7 +1761,7 @@ vrrp_autoconfig_autocreate(struct interface *mvl_ifp)
        struct interface *p;
        struct vrrp_vrouter *vr;
 
-       p = if_lookup_by_index(mvl_ifp->link_ifindex, VRF_DEFAULT);
+       p = if_lookup_by_index(mvl_ifp->link_ifindex, mvl_ifp->vrf_id);
 
        if (!p)
                return NULL;
@@ -1999,11 +2038,13 @@ int vrrp_autoconfig(void)
        if (!vrrp_autoconfig_is_on)
                return 0;
 
-       struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+       struct vrf *vrf;
        struct interface *ifp;
 
-       FOR_ALL_INTERFACES (vrf, ifp)
-               vrrp_autoconfig_if_add(ifp);
+       RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+               FOR_ALL_INTERFACES (vrf, ifp)
+                       vrrp_autoconfig_if_add(ifp);
+       }
 
        return 0;
 }
@@ -2258,71 +2299,6 @@ void vrrp_if_address_del(struct interface *ifp)
 
 /* Other ------------------------------------------------------------------- */
 
-int vrrp_config_write_interface(struct vty *vty)
-{
-       struct list *vrs = hash_to_list(vrrp_vrouters_hash);
-       struct listnode *ln, *ipln;
-       struct vrrp_vrouter *vr;
-       int writes = 0;
-
-       for (ALL_LIST_ELEMENTS_RO(vrs, ln, vr)) {
-               vty_frame(vty, "interface %s\n", vr->ifp->name);
-               ++writes;
-
-               vty_out(vty, " vrrp %" PRIu8 "%s\n", vr->vrid,
-                       vr->version == 2 ? " version 2" : "");
-               ++writes;
-
-               if (vr->shutdown != vd.shutdown && ++writes)
-                       vty_out(vty, " %svrrp %" PRIu8 " shutdown\n",
-                               vr->shutdown ? "" : "no ", vr->vrid);
-
-               if (vr->preempt_mode != vd.preempt_mode && ++writes)
-                       vty_out(vty, " %svrrp %" PRIu8 " preempt\n",
-                               vr->preempt_mode ? "" : "no ", vr->vrid);
-
-               if (vr->accept_mode != vd.accept_mode && ++writes)
-                       vty_out(vty, " %svrrp %" PRIu8 " accept\n",
-                               vr->accept_mode ? "" : "no ", vr->vrid);
-
-               if (vr->advertisement_interval != vd.advertisement_interval
-                   && ++writes)
-                       vty_out(vty,
-                               " vrrp %" PRIu8
-                               " advertisement-interval %d\n",
-                               vr->vrid, vr->advertisement_interval * CS2MS);
-
-               if (vr->priority != vd.priority && ++writes)
-                       vty_out(vty, " vrrp %" PRIu8 " priority %" PRIu8 "\n",
-                               vr->vrid, vr->priority);
-
-               struct ipaddr *ip;
-
-               for (ALL_LIST_ELEMENTS_RO(vr->v4->addrs, ipln, ip)) {
-                       char ipbuf[INET6_ADDRSTRLEN];
-
-                       ipaddr2str(ip, ipbuf, sizeof(ipbuf));
-                       vty_out(vty, " vrrp %" PRIu8 " ip %s\n", vr->vrid,
-                               ipbuf);
-                       ++writes;
-               }
-
-               for (ALL_LIST_ELEMENTS_RO(vr->v6->addrs, ipln, ip)) {
-                       char ipbuf[INET6_ADDRSTRLEN];
-
-                       ipaddr2str(ip, ipbuf, sizeof(ipbuf));
-                       vty_out(vty, " vrrp %" PRIu8 " ipv6 %s\n", vr->vrid,
-                               ipbuf);
-                       ++writes;
-               }
-               vty_endframe(vty, "!\n");
-       }
-
-       list_delete(&vrs);
-
-       return writes;
-}
-
 int vrrp_config_write_global(struct vty *vty)
 {
        unsigned int writes = 0;
@@ -2331,6 +2307,7 @@ int vrrp_config_write_global(struct vty *vty)
                vty_out(vty, "vrrp autoconfigure%s\n",
                        vrrp_autoconfig_version == 2 ? " version 2" : "");
 
+       /* FIXME: needs to be udpated for full YANG conversion. */
        if (vd.priority != VRRP_DEFAULT_PRIORITY && ++writes)
                vty_out(vty, "vrrp default priority %" PRIu8 "\n", vd.priority);
 
@@ -2380,10 +2357,13 @@ static bool vrrp_hash_cmp(const void *arg1, const void *arg2)
 void vrrp_init(void)
 {
        /* Set default defaults */
-       vd.priority = VRRP_DEFAULT_PRIORITY;
-       vd.advertisement_interval = VRRP_DEFAULT_ADVINT;
-       vd.preempt_mode = VRRP_DEFAULT_PREEMPT;
-       vd.accept_mode = VRRP_DEFAULT_ACCEPT;
+       vd.version = yang_get_default_uint8("%s/version", VRRP_XPATH_FULL);
+       vd.priority = yang_get_default_uint8("%s/priority", VRRP_XPATH_FULL);
+       vd.advertisement_interval = yang_get_default_uint16(
+               "%s/advertisement-interval", VRRP_XPATH_FULL);
+       vd.preempt_mode = yang_get_default_bool("%s/preempt", VRRP_XPATH_FULL);
+       vd.accept_mode =
+               yang_get_default_bool("%s/accept-mode", VRRP_XPATH_FULL);
        vd.shutdown = VRRP_DEFAULT_SHUTDOWN;
 
        vrrp_autoconfig_version = 3;