/* 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;
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
*/
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.
*/
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");
}
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;
}
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,
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");
}
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;
}