]> git.puffer.fish Git - matthieu/frr.git/commitdiff
*: Refine the notion of a configured VRF in FRR
authorvivek <vivek@cumulusnetworks.com>
Wed, 6 Dec 2017 23:19:11 +0000 (15:19 -0800)
committermitesh <mitesh@cumulusnetworks.com>
Wed, 24 Jan 2018 02:49:40 +0000 (18:49 -0800)
Refine the notion of what FRR considers as "configured" VRF. It is no longer
based on user just typing "vrf FOO" but when something is actually configured
against that VRF. Right now, in zebra, the only configuration against a VRF
are static IP routes and EVPN L3 VNI. Whenever a configuration is removed,
check and clear the "configured" flag if there is no other configuration for
this VRF. When user attempts to configure a static route and the VRF doesn't
exist, a VRF is created; the VRF is only active when also defined in the
kernel.

Updates: 8b73ea7bd479030418ca06eef59d0648d913b620
Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com>
Reviewed-by: Don Slice <dslice@cumulusnetworks.com>
Ticket: CM-10139, CM-18553
Reviewed By: CCR-7019
Testing Done:
1. Manual testing for L3 VNI and static routes - FRR restart, networking
restart etc.
2. 'vrf' smoke

<DETAILED DESCRIPTION (REPLACE)>

lib/vrf.c
lib/vrf.h
zebra/zebra_vrf.c
zebra/zebra_vrf.h
zebra/zebra_vty.c
zebra/zebra_vxlan.c

index 23eaa042ec1991575870e3da7c0010c5eae74177..2e15fa2f5c2c0c884b99cd6f2fdc0b68d3e1ab79 100644 (file)
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -462,9 +462,6 @@ DEFUN_NOSH (vrf,
 
        vrfp = vrf_get(VRF_UNKNOWN, vrfname);
 
-       /* Mark as user configured. */
-       SET_FLAG(vrfp->status, VRF_CONFIGURED);
-
        VTY_PUSH_CONTEXT(VRF_NODE, vrfp);
 
        return CMD_SUCCESS;
index 89d2316354ccc2136212c3fdb5ad1937bc9ff4aa..99c048c7025361987d7ab700fb05d0a2dff2b740 100644 (file)
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -76,7 +76,7 @@ struct vrf {
        /* Zebra internal VRF status */
        u_char status;
 #define VRF_ACTIVE     (1 << 0) /* VRF is up in kernel */
-#define VRF_CONFIGURED (1 << 1) /* VRF is configured by user in frr */
+#define VRF_CONFIGURED (1 << 1) /* VRF has some FRR configuration */
 
        /* Interfaces belonging to this VRF */
        struct if_name_head ifaces_by_name;
@@ -134,6 +134,18 @@ static inline int vrf_is_user_cfged(struct vrf *vrf)
        return vrf && CHECK_FLAG(vrf->status, VRF_CONFIGURED);
 }
 
+/* Mark that VRF has user configuration */
+static inline void vrf_set_user_cfged(struct vrf *vrf)
+{
+       SET_FLAG(vrf->status, VRF_CONFIGURED);
+}
+
+/* Mark that VRF no longer has any user configuration */
+static inline void vrf_reset_user_cfged(struct vrf *vrf)
+{
+       UNSET_FLAG(vrf->status, VRF_CONFIGURED);
+}
+
 /*
  * Utilities to obtain the user data
  */
index 54c9f573c94375eaab293ddc79ffe031fc4c52d6..4310bd394d3f0359d837efa3b854992aa66ed1f9 100644 (file)
@@ -351,6 +351,37 @@ static int zebra_vrf_delete(struct vrf *vrf)
        return 0;
 }
 
+/* Return if this VRF has any FRR configuration or not.
+ * IMPORTANT: This function needs to be updated when additional configuration
+ * is added for a VRF.
+ */
+int zebra_vrf_has_config(struct zebra_vrf *zvrf)
+{
+       afi_t afi;
+       safi_t safi;
+       struct route_table *stable;
+
+       /* NOTE: This is a don't care for the default VRF, but we go through
+        * the motions to keep things consistent.
+        */
+       /* Any static routes? */
+       for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+               for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
+                       stable = zvrf->stable[afi][safi];
+                       if (!stable)
+                               continue;
+                       if (route_table_count(stable))
+                               return 1;
+               }
+       }
+
+       /* EVPN L3-VNI? */
+       if (zvrf->l3vni)
+               return 1;
+
+       return 0;
+}
+
 /* Lookup the routing table in a VRF based on both VRF-Id and table-id.
  * NOTE: Table-id is relevant only in the Default VRF.
  */
@@ -565,14 +596,15 @@ static int vrf_config_write(struct vty *vty)
 
                if (vrf_is_user_cfged(vrf)) {
                        vty_out(vty, "vrf %s\n", zvrf_name(zvrf));
+                       if (zvrf->l3vni)
+                               vty_out(vty, " vni %u\n", zvrf->l3vni);
+                       vty_out(vty, "!\n");
+               }
 
                static_config(vty, zvrf, AFI_IP, SAFI_UNICAST, "ip route");
                static_config(vty, zvrf, AFI_IP, SAFI_MULTICAST, "ip mroute");
                static_config(vty, zvrf, AFI_IP6, SAFI_UNICAST, "ipv6 route");
 
-               if (vrf->vrf_id != VRF_DEFAULT && zvrf->l3vni)
-                       vty_out(vty, " vni %u\n", zvrf->l3vni);
-
                if (vrf->vrf_id != VRF_DEFAULT)
                        vty_out(vty, "!\n");
        }
index c7a0717ee8291bc655f3bfff7e1f23d3ade2e00c..fe7e77e8bee7c47bceb785c26888fd812f888b0f 100644 (file)
@@ -149,5 +149,6 @@ extern struct route_table *zebra_vrf_static_table(afi_t, safi_t,
                                                  struct zebra_vrf *zvrf);
 extern struct route_table *
 zebra_vrf_other_route_table(afi_t afi, u_int32_t table_id, vrf_id_t vrf_id);
+extern int zebra_vrf_has_config(struct zebra_vrf *zvrf);
 extern void zebra_vrf_init(void);
 #endif
index bc6a18d3b532f182f8503414391ec58317acce1c..89ae1e81c39169c15127b01e020dd2ce2a2e716e 100644 (file)
@@ -231,13 +231,19 @@ static int zebra_static_route_leak(struct vty *vty,
                        type = STATIC_IPV6_GATEWAY;
        }
 
-       if (!negate)
+       if (!negate) {
                static_add_route(afi, safi, type, &p, src_p, gatep, ifname,
                                 bh_type, tag, distance, zvrf, nh_zvrf,
                                 &snh_label);
-       else
+               /* Mark as having FRR configuration */
+               vrf_set_user_cfged(zvrf->vrf);
+       } else {
                static_delete_route(afi, safi, type, &p, src_p, gatep, ifname,
                                    tag, distance, zvrf, &snh_label);
+               /* If no other FRR config for this VRF, mark accordingly. */
+               if (!zebra_vrf_has_config(zvrf))
+                       vrf_reset_user_cfged(zvrf->vrf);
+       }
 
        return CMD_SUCCESS;
 }
@@ -247,19 +253,39 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
                              const char *mask_str, const char *src_str,
                              const char *gate_str, const char *ifname,
                              const char *flag_str, const char *tag_str,
-                             const char *distance_str, const char *vrf_id_str,
+                             const char *distance_str, const char *vrf_name,
                              const char *label_str)
 {
        struct zebra_vrf *zvrf;
+       struct vrf *vrf;
 
        /* VRF id */
-       zvrf = zebra_vrf_lookup_by_name(vrf_id_str);
+       zvrf = zebra_vrf_lookup_by_name(vrf_name);
 
-       if (!zvrf) {
-               vty_out(vty, "%% vrf %s is not defined\n", vrf_id_str);
+       /* When trying to delete, the VRF must exist. */
+       if (negate && !zvrf) {
+               vty_out(vty, "%% vrf %s is not defined\n", vrf_name);
                return CMD_WARNING_CONFIG_FAILED;
        }
 
+       /* When trying to create, create the VRF if it doesn't exist.
+        * Note: The VRF isn't active until we hear about it from the kernel.
+        */
+       if (!zvrf) {
+               vrf = vrf_get(VRF_UNKNOWN, vrf_name);
+               if (!vrf) {
+                       vty_out(vty, "%% Could not create vrf %s\n", vrf_name);
+                       return CMD_WARNING_CONFIG_FAILED;
+               }
+               zvrf = vrf->info;
+               if (!zvrf) {
+                       vty_out(vty, "%% Could not create vrf-info %s\n",
+                               vrf_name);
+                       return CMD_WARNING_CONFIG_FAILED;
+               }
+               /* Mark as having FRR configuration */
+               vrf_set_user_cfged(vrf);
+       }
        return zebra_static_route_leak(vty, zvrf, zvrf, afi, safi,
                                       negate, dest_str, mask_str, src_str,
                                       gate_str, ifname, flag_str, tag_str,
@@ -2269,6 +2295,8 @@ DEFUN (show_vrf,
                else
                        vty_out(vty, "id %u table %u", zvrf_id(zvrf),
                                zvrf->table_id);
+               if (vrf_is_user_cfged(vrf))
+                       vty_out(vty, " (configured)");
                vty_out(vty, "\n");
        }
 
@@ -2372,6 +2400,10 @@ DEFUN (no_vrf_vni_mapping,
                return CMD_WARNING;
        }
 
+       /* If no other FRR config for this VRF, mark accordingly. */
+       if (!zebra_vrf_has_config(zvrf))
+               vrf_reset_user_cfged(vrf);
+
        return CMD_SUCCESS;
 }
 
index 750dfc4ea8b489a7a47553767634608835b83830..fb1aebecc3599596a7d200f2c013b88f220e0de2 100644 (file)
@@ -3801,7 +3801,7 @@ static int ip_prefix_send_to_client(vrf_id_t vrf_id,
        s = client->obuf;
        stream_reset(s);
 
-       zserv_create_header(s, cmd, vrf_id);
+       zclient_create_header(s, cmd, vrf_id);
        stream_put(s, p, sizeof(struct prefix));
 
        /* Write packet size. */