]> git.proxmox.com Git - mirror_frr.git/commitdiff
ripngd: add VRF support
authorRenato Westphal <renato@opensourcerouting.org>
Fri, 4 Jan 2019 21:08:10 +0000 (19:08 -0200)
committerRenato Westphal <renato@opensourcerouting.org>
Fri, 18 Jan 2019 18:15:41 +0000 (16:15 -0200)
* Turn the "instance" YANG presence-container into a YANG list keyed
  by the new "vrf" leaf. This is a backward incompatible change but
  this should be ok for now.

* RIPng VRF instances can be configured even when the corresponding
  VRF doesn't exist. And a RIPng VRF instance isn't deleted when
  the corresponding VRF is deleted. For this to work, implement the
  ripng_instance_enable() and ripng_instance_disable() functions
  that are called to enable/disable RIPng routing instances when
  necessary. A RIPng routing instance can be enabled only when the
  corresponding VRF is enabled (this information comes from zebra
  and depends on the underlying VRF backend). Routing instances are
  stored in the new ripng_instances rb-tree (global variable).

* Add a vrf pointer to the ripng structure instead of storing vrf_id
  only. This is much more convenient than using vrf_lookup_by_id()
  every time we need to get the vrf pointer from the VRF ID. The
  ripng->vrf pointer is updated whenever the VRF enable/disable hooks
  are called.

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
ripngd/ripng_cli.c
ripngd/ripng_interface.c
ripngd/ripng_main.c
ripngd/ripng_memory.c
ripngd/ripng_memory.h
ripngd/ripng_northbound.c
ripngd/ripng_zebra.c
ripngd/ripngd.c
ripngd/ripngd.h
vtysh/vtysh.c
yang/frr-ripngd.yang

index a187e80fd7a4691a79e507ad6ada5a1c6900f766..c89832d51d30c1ba027f13d7e68d27e12110b01e 100644 (file)
  */
 DEFPY_NOSH (router_ripng,
        router_ripng_cmd,
-       "router ripng",
+       "router ripng [vrf NAME]",
        "Enable a routing process\n"
-       "Make RIPng instance command\n")
+       "Make RIPng instance command\n"
+       VRF_CMD_HELP_STR)
 {
+       char xpath[XPATH_MAXLEN];
        int ret;
 
-       nb_cli_enqueue_change(vty, "/frr-ripngd:ripngd/instance", NB_OP_CREATE,
-                             NULL);
+       /* Build RIPng instance XPath. */
+       if (!vrf)
+               vrf = VRF_DEFAULT_NAME;
+       snprintf(xpath, sizeof(xpath), "/frr-ripngd:ripngd/instance[vrf='%s']",
+                vrf);
+
+       nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
 
        ret = nb_cli_apply_changes(vty, NULL);
        if (ret == CMD_SUCCESS)
-               VTY_PUSH_XPATH(RIPNG_NODE, "/frr-ripngd:ripngd/instance");
+               VTY_PUSH_XPATH(RIPNG_NODE, xpath);
 
        return ret;
 }
 
 DEFPY (no_router_ripng,
        no_router_ripng_cmd,
-       "no router ripng",
+       "no router ripng [vrf NAME]",
        NO_STR
        "Enable a routing process\n"
-       "Make RIPng instance command\n")
+       "Make RIPng instance command\n"
+       VRF_CMD_HELP_STR)
 {
-       nb_cli_enqueue_change(vty, "/frr-ripngd:ripngd/instance", NB_OP_DELETE,
-                             NULL);
+       char xpath[XPATH_MAXLEN];
+
+       /* Build RIPng instance XPath. */
+       if (!vrf)
+               vrf = VRF_DEFAULT_NAME;
+       snprintf(xpath, sizeof(xpath), "/frr-ripngd:ripngd/instance[vrf='%s']",
+                vrf);
+
+       nb_cli_enqueue_change(vty, xpath, NB_OP_DELETE, NULL);
 
        return nb_cli_apply_changes(vty, NULL);
 }
@@ -71,8 +86,15 @@ DEFPY (no_router_ripng,
 void cli_show_router_ripng(struct vty *vty, struct lyd_node *dnode,
                         bool show_defaults)
 {
+       const char *vrf_name;
+
+       vrf_name = yang_dnode_get_string(dnode, "./vrf");
+
        vty_out(vty, "!\n");
-       vty_out(vty, "router ripng\n");
+       vty_out(vty, "router ripng");
+       if (!strmatch(vrf_name, VRF_DEFAULT_NAME))
+               vty_out(vty, " vrf %s", vrf_name);
+       vty_out(vty, "\n");
 }
 
 /*
index af2b1c260a0f2ef5b0e77d174234149117f7272b..edc258c05b66a94c7ce004c51f69bc7fde73b29a 100644 (file)
@@ -209,9 +209,11 @@ int ripng_interface_up(int command, struct zclient *zclient,
 
        if (IS_RIPNG_DEBUG_ZEBRA)
                zlog_debug(
-                       "interface up %s index %d flags %llx metric %d mtu %d",
-                       ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
-                       ifp->metric, ifp->mtu6);
+                       "interface up %s vrf %u index %d flags %llx metric %d mtu %d",
+                       ifp->name, ifp->vrf_id, ifp->ifindex,
+                       (unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
+
+       ripng_interface_sync(ifp);
 
        /* Check if this interface is RIPng enabled or not. */
        ripng_enable_apply(ifp);
@@ -240,13 +242,14 @@ int ripng_interface_down(int command, struct zclient *zclient,
        if (ifp == NULL)
                return 0;
 
+       ripng_interface_sync(ifp);
        ripng_if_down(ifp);
 
        if (IS_RIPNG_DEBUG_ZEBRA)
                zlog_debug(
-                       "interface down %s index %d flags %#llx metric %d mtu %d",
-                       ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
-                       ifp->metric, ifp->mtu6);
+                       "interface down %s vrf %u index %d flags %#llx metric %d mtu %d",
+                       ifp->name, ifp->vrf_id, ifp->ifindex,
+                       (unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
 
        return 0;
 }
@@ -258,12 +261,13 @@ int ripng_interface_add(int command, struct zclient *zclient,
        struct interface *ifp;
 
        ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
+       ripng_interface_sync(ifp);
 
        if (IS_RIPNG_DEBUG_ZEBRA)
                zlog_debug(
-                       "RIPng interface add %s index %d flags %#llx metric %d mtu %d",
-                       ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
-                       ifp->metric, ifp->mtu6);
+                       "RIPng interface add %s vrf %u index %d flags %#llx metric %d mtu %d",
+                       ifp->name, ifp->vrf_id, ifp->ifindex,
+                       (unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
 
        /* Check is this interface is RIP enabled or not.*/
        ripng_enable_apply(ifp);
@@ -291,13 +295,15 @@ int ripng_interface_delete(int command, struct zclient *zclient,
        if (ifp == NULL)
                return 0;
 
+       ripng_interface_sync(ifp);
        if (if_is_up(ifp)) {
                ripng_if_down(ifp);
        }
 
-       zlog_info("interface delete %s index %d flags %#llx metric %d mtu %d",
-                 ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
-                 ifp->metric, ifp->mtu6);
+       zlog_info(
+               "interface delete %s vrf %u index %d flags %#llx metric %d mtu %d",
+               ifp->name, ifp->vrf_id, ifp->ifindex,
+               (unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
 
        /* To support pseudo interface do not free interface structure.  */
        /* if_delete(ifp); */
@@ -306,13 +312,34 @@ int ripng_interface_delete(int command, struct zclient *zclient,
        return 0;
 }
 
+/* VRF update for an interface. */
+int ripng_interface_vrf_update(int command, struct zclient *zclient,
+                              zebra_size_t length, vrf_id_t vrf_id)
+{
+       struct interface *ifp;
+       vrf_id_t new_vrf_id;
+
+       ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,
+                                             &new_vrf_id);
+       if (!ifp)
+               return 0;
+
+       if (IS_RIPNG_DEBUG_ZEBRA)
+               zlog_debug("interface %s VRF change vrf_id %u new vrf id %u",
+                          ifp->name, vrf_id, new_vrf_id);
+
+       if_update_to_new_vrf(ifp, new_vrf_id);
+       ripng_interface_sync(ifp);
+
+       return 0;
+}
+
 void ripng_interface_clean(struct ripng *ripng)
 {
-       struct vrf *vrf = vrf_lookup_by_id(ripng->vrf_id);
        struct interface *ifp;
        struct ripng_interface *ri;
 
-       FOR_ALL_INTERFACES (vrf, ifp) {
+       FOR_ALL_INTERFACES (ripng->vrf, ifp) {
                ri = ifp->info;
 
                ri->enable_network = 0;
@@ -748,10 +775,9 @@ void ripng_enable_apply(struct interface *ifp)
 /* Set distribute list to all interfaces. */
 static void ripng_enable_apply_all(struct ripng *ripng)
 {
-       struct vrf *vrf = vrf_lookup_by_id(ripng->vrf_id);
        struct interface *ifp;
 
-       FOR_ALL_INTERFACES (vrf, ifp)
+       FOR_ALL_INTERFACES (ripng->vrf, ifp)
                ripng_enable_apply(ifp);
 }
 
@@ -812,10 +838,9 @@ void ripng_passive_interface_apply(struct interface *ifp)
 
 static void ripng_passive_interface_apply_all(struct ripng *ripng)
 {
-       struct vrf *vrf = vrf_lookup_by_id(ripng->vrf_id);
        struct interface *ifp;
 
-       FOR_ALL_INTERFACES (vrf, ifp)
+       FOR_ALL_INTERFACES (ripng->vrf, ifp)
                ripng_passive_interface_apply(ifp);
 }
 
@@ -890,17 +915,12 @@ int ripng_network_write(struct vty *vty, struct ripng *ripng)
        return 0;
 }
 
-static struct ripng_interface *ri_new(struct interface *ifp)
+static struct ripng_interface *ri_new(void)
 {
-       struct vrf *vrf;
        struct ripng_interface *ri;
 
        ri = XCALLOC(MTYPE_IF, sizeof(struct ripng_interface));
 
-       vrf = vrf_lookup_by_id(ifp->vrf_id);
-       if (vrf)
-               ri->ripng = vrf->info;
-
        /* Set default split-horizon behavior.  If the interface is Frame
           Relay or SMDS is enabled, the default value for split-horizon is
           off.  But currently Zebra does detect Frame Relay or SMDS
@@ -911,9 +931,25 @@ static struct ripng_interface *ri_new(struct interface *ifp)
        return ri;
 }
 
+void ripng_interface_sync(struct interface *ifp)
+{
+       struct vrf *vrf;
+
+       vrf = vrf_lookup_by_id(ifp->vrf_id);
+       if (vrf) {
+               struct ripng_interface *ri;
+
+               ri = ifp->info;
+               if (ri)
+                       ri->ripng = vrf->info;
+       }
+}
+
 static int ripng_if_new_hook(struct interface *ifp)
 {
-       ifp->info = ri_new(ifp);
+       ifp->info = ri_new();
+       ripng_interface_sync(ifp);
+
        return 0;
 }
 
@@ -928,22 +964,25 @@ static int ripng_if_delete_hook(struct interface *ifp)
 /* Configuration write function for ripngd. */
 static int interface_config_write(struct vty *vty)
 {
-       struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
-       struct interface *ifp;
+       struct vrf *vrf;
        int write = 0;
 
-       FOR_ALL_INTERFACES (vrf, ifp) {
-               struct lyd_node *dnode;
+       RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+               struct interface *ifp;
 
-               dnode = yang_dnode_get(
-                       running_config->dnode,
-                       "/frr-interface:lib/interface[name='%s'][vrf='%s']",
-                       ifp->name, vrf->name);
-               if (dnode == NULL)
-                       continue;
+               FOR_ALL_INTERFACES (vrf, ifp) {
+                       struct lyd_node *dnode;
+
+                       dnode = yang_dnode_get(
+                               running_config->dnode,
+                               "/frr-interface:lib/interface[name='%s'][vrf='%s']",
+                               ifp->name, vrf->name);
+                       if (dnode == NULL)
+                               continue;
 
-               write = 1;
-               nb_cli_show_dnode_cmds(vty, dnode, false);
+                       write = 1;
+                       nb_cli_show_dnode_cmds(vty, dnode, false);
+               }
        }
 
        return write;
index e7246efc4399ba0ac427a5bd584d5b07133a7247..37b163c5e41191935321852714b42a5736b1e9d4 100644 (file)
@@ -46,7 +46,7 @@
 struct option longopts[] = {{"retain", no_argument, NULL, 'r'}, {0}};
 
 /* ripngd privileges */
-zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND};
+zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND, ZCAP_SYS_ADMIN};
 
 struct zebra_privs_t ripngd_privs = {
 #if defined(FRR_USER)
@@ -59,7 +59,7 @@ struct zebra_privs_t ripngd_privs = {
        .vty_group = VTY_GROUP,
 #endif
        .caps_p = _caps_p,
-       .cap_num_p = 2,
+       .cap_num_p = array_size(_caps_p),
        .cap_num_i = 0};
 
 
@@ -80,18 +80,9 @@ static void sighup(void)
 /* SIGINT handler. */
 static void sigint(void)
 {
-       struct vrf *vrf;
-
        zlog_notice("Terminating on signal");
 
-       RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
-               struct ripng *ripng;
-
-               ripng = vrf->info;
-               if (ripng)
-                       ripng_clean(ripng);
-       }
-
+       ripng_vrf_terminate();
        ripng_zebra_stop();
        frr_fini();
        exit(0);
@@ -178,7 +169,7 @@ int main(int argc, char **argv)
        master = frr_init();
 
        /* Library inits. */
-       vrf_init(NULL, NULL, NULL, NULL, NULL);
+       ripng_vrf_init();
 
        /* RIPngd inits. */
        ripng_init();
index 0cb24052e60c9b0abbd6d1c02a4ea53411c6fd39..f459566bed35c89ba6b81de59fe04d70bdcb0954 100644 (file)
@@ -27,6 +27,7 @@
 
 DEFINE_MGROUP(RIPNGD, "ripngd")
 DEFINE_MTYPE(RIPNGD, RIPNG, "RIPng structure")
+DEFINE_MTYPE(RIPNGD, RIPNG_VRF_NAME, "RIPng VRF name")
 DEFINE_MTYPE(RIPNGD, RIPNG_ROUTE, "RIPng route info")
 DEFINE_MTYPE(RIPNGD, RIPNG_AGGREGATE, "RIPng aggregate")
 DEFINE_MTYPE(RIPNGD, RIPNG_PEER, "RIPng peer")
index a4102086c7f50ad858732b4f9a2d0afc9aefe7fe..3dfc57b3ffdb1afcb5111e026da61a664cf71305 100644 (file)
@@ -26,6 +26,7 @@
 
 DECLARE_MGROUP(RIPNGD)
 DECLARE_MTYPE(RIPNG)
+DECLARE_MTYPE(RIPNG_VRF_NAME)
 DECLARE_MTYPE(RIPNG_ROUTE)
 DECLARE_MTYPE(RIPNG_AGGREGATE)
 DECLARE_MTYPE(RIPNG_PEER)
index a6700c845429dbeba143af38c7b74fd4163e14ed..9784d0c20076e9bc5eab725856b636343822705a 100644 (file)
@@ -44,25 +44,42 @@ static int ripngd_instance_create(enum nb_event event,
 {
        struct ripng *ripng;
        struct vrf *vrf;
+       const char *vrf_name;
        int socket;
 
+       vrf_name = yang_dnode_get_string(dnode, "./vrf");
+       vrf = vrf_lookup_by_name(vrf_name);
+
+       /*
+        * Try to create a RIPng socket only if the VRF is enabled, otherwise
+        * create a disabled RIPng instance and wait for the VRF to be enabled.
+        */
        switch (event) {
        case NB_EV_VALIDATE:
                break;
        case NB_EV_PREPARE:
-               socket = ripng_make_socket();
+               if (!vrf || !vrf_is_enabled(vrf))
+                       break;
+
+               socket = ripng_make_socket(vrf);
                if (socket < 0)
                        return NB_ERR_RESOURCE;
                resource->fd = socket;
                break;
        case NB_EV_ABORT:
+               if (!vrf || !vrf_is_enabled(vrf))
+                       break;
+
                socket = resource->fd;
                close(socket);
                break;
        case NB_EV_APPLY:
-               vrf = vrf_lookup_by_id(VRF_DEFAULT);
-               socket = resource->fd;
-               ripng = ripng_create(vrf, socket);
+               if (vrf && vrf_is_enabled(vrf))
+                       socket = resource->fd;
+               else
+                       socket = -1;
+
+               ripng = ripng_create(vrf_name, vrf, socket);
                yang_dnode_set_entry(dnode, ripng);
                break;
        }
index 9e8dd03cbc8fb61502336eb35ae1dc25ee4daafb..913ac5191c23eafa7582c689e9b08b5fca856ab2 100644 (file)
@@ -48,7 +48,7 @@ static void ripng_zebra_ipv6_send(struct ripng *ripng, struct agg_node *rp,
        int count = 0;
 
        memset(&api, 0, sizeof(api));
-       api.vrf_id = ripng->vrf_id;
+       api.vrf_id = ripng->vrf->vrf_id;
        api.type = ZEBRA_ROUTE_RIPNG;
        api.safi = SAFI_UNICAST;
        api.prefix = rp->p;
@@ -58,7 +58,7 @@ static void ripng_zebra_ipv6_send(struct ripng *ripng, struct agg_node *rp,
                if (count >= MULTIPATH_NUM)
                        break;
                api_nh = &api.nexthops[count];
-               api_nh->vrf_id = ripng->vrf_id;
+               api_nh->vrf_id = ripng->vrf->vrf_id;
                api_nh->gate.ipv6 = rinfo->nexthop;
                api_nh->ifindex = rinfo->ifindex;
                api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
@@ -151,36 +151,38 @@ static int ripng_zebra_read_route(int command, struct zclient *zclient,
 void ripng_redistribute_conf_update(struct ripng *ripng, int type)
 {
        zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0,
-                            ripng->vrf_id);
+                            ripng->vrf->vrf_id);
 }
 
 void ripng_redistribute_conf_delete(struct ripng *ripng, int type)
 {
        if (zclient->sock > 0)
                zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
-                                       AFI_IP6, type, 0, ripng->vrf_id);
+                                       AFI_IP6, type, 0, ripng->vrf->vrf_id);
 
        ripng_redistribute_withdraw(ripng, type);
 }
 
 int ripng_redistribute_check(struct ripng *ripng, int type)
 {
-       return vrf_bitmap_check(zclient->redist[AFI_IP6][type], ripng->vrf_id);
+       return vrf_bitmap_check(zclient->redist[AFI_IP6][type],
+                               ripng->vrf->vrf_id);
 }
 
 void ripng_redistribute_clean(struct ripng *ripng)
 {
        for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
                if (!vrf_bitmap_check(zclient->redist[AFI_IP6][i],
-                                     ripng->vrf_id))
+                                     ripng->vrf->vrf_id))
                        continue;
 
                if (zclient->sock > 0)
                        zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE,
                                                zclient, AFI_IP6, i, 0,
-                                               ripng->vrf_id);
+                                               ripng->vrf->vrf_id);
 
-               vrf_bitmap_unset(zclient->redist[AFI_IP6][i], ripng->vrf_id);
+               vrf_bitmap_unset(zclient->redist[AFI_IP6][i],
+                                ripng->vrf->vrf_id);
        }
 }
 
@@ -191,13 +193,37 @@ void ripng_redistribute_write(struct vty *vty, struct ripng *ripng)
        for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
                if (i == zclient->redist_default
                    || !vrf_bitmap_check(zclient->redist[AFI_IP6][i],
-                                        ripng->vrf_id))
+                                        ripng->vrf->vrf_id))
                        continue;
 
                vty_out(vty, "    %s", zebra_route_string(i));
        }
 }
 
+void ripng_zebra_vrf_register(struct vrf *vrf)
+{
+       if (vrf->vrf_id == VRF_DEFAULT)
+               return;
+
+       if (IS_RIPNG_DEBUG_EVENT)
+               zlog_debug("%s: register VRF %s(%u) to zebra", __func__,
+                          vrf->name, vrf->vrf_id);
+
+       zclient_send_reg_requests(zclient, vrf->vrf_id);
+}
+
+void ripng_zebra_vrf_deregister(struct vrf *vrf)
+{
+       if (vrf->vrf_id == VRF_DEFAULT)
+               return;
+
+       if (IS_RIPNG_DEBUG_EVENT)
+               zlog_debug("%s: deregister VRF %s(%u) from zebra.", __func__,
+                          vrf->name, vrf->vrf_id);
+
+       zclient_send_dereg_requests(zclient, vrf->vrf_id);
+}
+
 static void ripng_zebra_connected(struct zclient *zclient)
 {
        zclient_send_reg_requests(zclient, VRF_DEFAULT);
@@ -217,6 +243,7 @@ void zebra_init(struct thread_master *master)
        zclient->interface_delete = ripng_interface_delete;
        zclient->interface_address_add = ripng_interface_address_add;
        zclient->interface_address_delete = ripng_interface_address_delete;
+       zclient->interface_vrf_update = ripng_interface_vrf_update;
        zclient->redistribute_route_add = ripng_zebra_read_route;
        zclient->redistribute_route_del = ripng_zebra_read_route;
 }
index 292b3da6abef09f841f4d9e97c3f72cfa30c2884..951c73bc45f64337dce00926279dd043c4dba1d4 100644 (file)
@@ -52,9 +52,22 @@ static void ripng_distribute_update(struct distribute_ctx *ctx,
 
 /* Prototypes. */
 void ripng_output_process(struct interface *, struct sockaddr_in6 *, int);
+static void ripng_instance_enable(struct ripng *ripng, struct vrf *vrf,
+                                 int sock);
+static void ripng_instance_disable(struct ripng *ripng);
 
 int ripng_triggered_update(struct thread *);
 
+/* Generate rb-tree of RIPng instances. */
+static inline int ripng_instance_compare(const struct ripng *a,
+                                        const struct ripng *b)
+{
+       return strcmp(a->vrf_name, b->vrf_name);
+}
+RB_GENERATE(ripng_instance_head, ripng, entry, ripng_instance_compare)
+
+struct ripng_instance_head ripng_instances = RB_INITIALIZER(&ripng_instances);
+
 /* RIPng next hop specification. */
 struct ripng_nexthop {
        enum ripng_nexthop_type {
@@ -91,18 +104,30 @@ struct ripng *ripng_info_get_instance(const struct ripng_info *rinfo)
 }
 
 /* Create ripng socket. */
-int ripng_make_socket(void)
+int ripng_make_socket(struct vrf *vrf)
 {
        int ret;
        int sock;
        struct sockaddr_in6 ripaddr;
-
-       sock = socket(AF_INET6, SOCK_DGRAM, 0);
-       if (sock < 0) {
-               flog_err_sys(EC_LIB_SOCKET, "Can't make ripng socket");
-               return sock;
+       const char *vrf_dev = NULL;
+
+       /* Make datagram socket. */
+       if (vrf->vrf_id != VRF_DEFAULT)
+               vrf_dev = vrf->name;
+       frr_elevate_privs(&ripngd_privs)
+       {
+               sock = vrf_socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP,
+                                 vrf->vrf_id, vrf_dev);
+               if (sock < 0) {
+                       flog_err_sys(EC_LIB_SOCKET,
+                                    "Cannot create UDP socket: %s",
+                                    safe_strerror(errno));
+                       return -1;
+               }
        }
 
+       sockopt_reuseaddr(sock);
+       sockopt_reuseport(sock);
        setsockopt_so_recvbuf(sock, 8096);
        ret = setsockopt_ipv6_pktinfo(sock, 1);
        if (ret < 0)
@@ -631,7 +656,7 @@ static int ripng_filter(int ripng_distribute, struct prefix_ipv6 *p,
        }
 
        /* All interface filter check. */
-       dist = distribute_lookup(ripng->distribute_ctx, NULL);
+       dist = distribute_lookup(ri->ripng->distribute_ctx, NULL);
        if (dist) {
                if (dist->list[distribute]) {
                        alist = access_list_lookup(AFI_IP6,
@@ -968,13 +993,13 @@ void ripng_redistribute_add(struct ripng *ripng, int type, int sub_type,
                        zlog_debug(
                                "Redistribute new prefix %s/%d on the interface %s",
                                inet6_ntoa(p->prefix), p->prefixlen,
-                               ifindex2ifname(ifindex, ripng->vrf_id));
+                               ifindex2ifname(ifindex, ripng->vrf->vrf_id));
                else
                        zlog_debug(
                                "Redistribute new prefix %s/%d with nexthop %s on the interface %s",
                                inet6_ntoa(p->prefix), p->prefixlen,
                                inet6_ntoa(*nexthop),
-                               ifindex2ifname(ifindex, ripng->vrf_id));
+                               ifindex2ifname(ifindex, ripng->vrf->vrf_id));
        }
 
        ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
@@ -1020,8 +1045,9 @@ void ripng_redistribute_delete(struct ripng *ripng, int type, int sub_type,
                                                "infinity metric [delete]",
                                                inet6_ntoa(p->prefix),
                                                p->prefixlen,
-                                               ifindex2ifname(ifindex,
-                                                              ripng->vrf_id));
+                                               ifindex2ifname(
+                                                       ifindex,
+                                                       ripng->vrf->vrf_id));
 
                                ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
                        }
@@ -1062,8 +1088,9 @@ void ripng_redistribute_withdraw(struct ripng *ripng, int type)
                                                "Poisone %s/%d on the interface %s [withdraw]",
                                                inet6_ntoa(p->prefix),
                                                p->prefixlen,
-                                               ifindex2ifname(rinfo->ifindex,
-                                                              ripng->vrf_id));
+                                               ifindex2ifname(
+                                                       rinfo->ifindex,
+                                                       ripng->vrf->vrf_id));
                                }
 
                                ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
@@ -1313,27 +1340,29 @@ static int ripng_read(struct thread *thread)
                                STREAM_SIZE(ripng->ibuf), &from, &ifindex,
                                &hoplimit);
        if (len < 0) {
-               zlog_warn("RIPng recvfrom failed: %s.", safe_strerror(errno));
+               zlog_warn("RIPng recvfrom failed (VRF %s): %s.",
+                         ripng->vrf_name, safe_strerror(errno));
                return len;
        }
 
        /* Check RTE boundary.  RTE size (Packet length - RIPng header size
           (4)) must be multiple size of one RTE size (20). */
        if (((len - 4) % 20) != 0) {
-               zlog_warn("RIPng invalid packet size %d from %s", len,
-                         inet6_ntoa(from.sin6_addr));
+               zlog_warn("RIPng invalid packet size %d from %s (VRF %s)", len,
+                         inet6_ntoa(from.sin6_addr), ripng->vrf_name);
                ripng_peer_bad_packet(ripng, &from);
                return 0;
        }
 
        packet = (struct ripng_packet *)STREAM_DATA(ripng->ibuf);
-       ifp = if_lookup_by_index(ifindex, ripng->vrf_id);
+       ifp = if_lookup_by_index(ifindex, ripng->vrf->vrf_id);
 
        /* RIPng packet received. */
        if (IS_RIPNG_DEBUG_EVENT)
-               zlog_debug("RIPng packet received from %s port %d on %s",
-                          inet6_ntoa(from.sin6_addr), ntohs(from.sin6_port),
-                          ifp ? ifp->name : "unknown");
+               zlog_debug(
+                       "RIPng packet received from %s port %d on %s (VRF %s)",
+                       inet6_ntoa(from.sin6_addr), ntohs(from.sin6_port),
+                       ifp ? ifp->name : "unknown", ripng->vrf_name);
 
        /* Logging before packet checking. */
        if (IS_RIPNG_DEBUG_RECV)
@@ -1341,16 +1370,17 @@ static int ripng_read(struct thread *thread)
 
        /* Packet comes from unknown interface. */
        if (ifp == NULL) {
-               zlog_warn("RIPng packet comes from unknown interface %d",
-                         ifindex);
+               zlog_warn(
+                       "RIPng packet comes from unknown interface %d (VRF %s)",
+                       ifindex, ripng->vrf_name);
                return 0;
        }
 
        /* Packet version mismatch checking. */
        if (packet->version != ripng->version) {
                zlog_warn(
-                       "RIPng packet version %d doesn't fit to my version %d",
-                       packet->version, ripng->version);
+                       "RIPng packet version %d doesn't fit to my version %d (VRF %s)",
+                       packet->version, ripng->version, ripng->vrf_name);
                ripng_peer_bad_packet(ripng, &from);
                return 0;
        }
@@ -1364,7 +1394,8 @@ static int ripng_read(struct thread *thread)
                ripng_response_process(packet, len, &from, ifp, hoplimit);
                break;
        default:
-               zlog_warn("Invalid RIPng command %d", packet->command);
+               zlog_warn("Invalid RIPng command %d (VRF %s)", packet->command,
+                         ripng->vrf_name);
                ripng_peer_bad_packet(ripng, &from);
                break;
        }
@@ -1394,7 +1425,6 @@ static void ripng_clear_changed_flag(struct ripng *ripng)
 static int ripng_update(struct thread *t)
 {
        struct ripng *ripng = THREAD_ARG(t);
-       struct vrf *vrf = vrf_lookup_by_id(ripng->vrf_id);
        struct interface *ifp;
        struct ripng_interface *ri;
 
@@ -1406,7 +1436,7 @@ static int ripng_update(struct thread *t)
                zlog_debug("RIPng update timer expired!");
 
        /* Supply routes to each interface. */
-       FOR_ALL_INTERFACES (vrf, ifp) {
+       FOR_ALL_INTERFACES (ripng->vrf, ifp) {
                ri = ifp->info;
 
                if (if_is_loopback(ifp) || !if_is_up(ifp))
@@ -1465,7 +1495,6 @@ static int ripng_triggered_interval(struct thread *t)
 int ripng_triggered_update(struct thread *t)
 {
        struct ripng *ripng = THREAD_ARG(t);
-       struct vrf *vrf = vrf_lookup_by_id(ripng->vrf_id);
        struct interface *ifp;
        struct ripng_interface *ri;
        int interval;
@@ -1485,7 +1514,7 @@ int ripng_triggered_update(struct thread *t)
 
        /* Split Horizon processing is done when generating triggered
           updates as well as normal updates (see section 2.6). */
-       FOR_ALL_INTERFACES (vrf, ifp) {
+       FOR_ALL_INTERFACES (ripng->vrf, ifp) {
                ri = ifp->info;
 
                if (if_is_loopback(ifp) || !if_is_up(ifp))
@@ -1811,14 +1840,23 @@ struct ripng *ripng_lookup_by_vrf_id(vrf_id_t vrf_id)
        return vrf->info;
 }
 
+struct ripng *ripng_lookup_by_vrf_name(const char *vrf_name)
+{
+       struct ripng ripng;
+
+       ripng.vrf_name = (char *)vrf_name;
+
+       return RB_FIND(ripng_instance_head, &ripng_instances, &ripng);
+}
+
 /* Create new RIPng instance and set it to global variable. */
-struct ripng *ripng_create(struct vrf *vrf, int socket)
+struct ripng *ripng_create(const char *vrf_name, struct vrf *vrf, int socket)
 {
        struct ripng *ripng;
-       struct interface *ifp;
 
        /* Allocaste RIPng instance. */
        ripng = XCALLOC(MTYPE_RIPNG, sizeof(struct ripng));
+       ripng->vrf_name = XSTRDUP(MTYPE_RIPNG_VRF_NAME, vrf_name);
 
        /* Default version and timer values. */
        ripng->version = RIPNG_V1;
@@ -1850,31 +1888,23 @@ struct ripng *ripng_create(struct vrf *vrf, int socket)
                (int (*)(void *, void *))offset_list_cmp;
        ripng->offset_list_master->del =
                (void (*)(void *))ripng_offset_list_del;
-
-       /* Distribute list install. */
-       ripng->distribute_ctx = distribute_list_ctx_create(
-                                          vrf_lookup_by_id(VRF_DEFAULT));
+       ripng->distribute_ctx = distribute_list_ctx_create(vrf);
        distribute_list_add_hook(ripng->distribute_ctx,
                                 ripng_distribute_update);
        distribute_list_delete_hook(ripng->distribute_ctx,
                                    ripng_distribute_update);
-       /* Make socket. */
-       ripng->sock = socket;
-
-       /* Threads. */
-       ripng_event(ripng, RIPNG_READ, ripng->sock);
-       ripng_event(ripng, RIPNG_UPDATE_EVENT, 1);
 
-       /* Link RIPng instance to VRF. */
-       ripng->vrf_id = vrf->vrf_id;
-       vrf->info = ripng;
-       FOR_ALL_INTERFACES (vrf, ifp) {
-               struct ripng_interface *ri;
 
-               ri = ifp->info;
-               ri->ripng = ripng;
+       /* Enable the routing instance if possible. */
+       if (vrf && vrf_is_enabled(vrf))
+               ripng_instance_enable(ripng, vrf, socket);
+       else {
+               ripng->vrf = NULL;
+               ripng->sock = -1;
        }
 
+       RB_INSERT(ripng_instance_head, &ripng_instances, ripng);
+
        return ripng;
 }
 
@@ -2003,10 +2033,11 @@ static char *ripng_route_subtype_print(struct ripng_info *rinfo)
 
 DEFUN (show_ipv6_ripng,
        show_ipv6_ripng_cmd,
-       "show ipv6 ripng",
+       "show ipv6 ripng [vrf NAME]",
        SHOW_STR
        IPV6_STR
-       "Show RIPng routes\n")
+       "Show RIPng routes\n"
+       VRF_CMD_HELP_STR)
 {
        struct ripng *ripng;
        struct agg_node *rp;
@@ -2016,10 +2047,23 @@ DEFUN (show_ipv6_ripng,
        struct list *list = NULL;
        struct listnode *listnode = NULL;
        int len;
+       const char *vrf_name;
+       int idx = 0;
 
-       ripng = ripng_lookup_by_vrf_id(VRF_DEFAULT);
-       if (!ripng)
+       if (argv_find(argv, argc, "vrf", &idx))
+               vrf_name = argv[idx + 1]->arg;
+       else
+               vrf_name = VRF_DEFAULT_NAME;
+
+       ripng = ripng_lookup_by_vrf_name(vrf_name);
+       if (!ripng) {
+               vty_out(vty, "%% RIPng instance not found\n");
+               return CMD_SUCCESS;
+       }
+       if (!ripng->enabled) {
+               vty_out(vty, "%% RIPng instance is disabled\n");
                return CMD_SUCCESS;
+       }
 
        /* Header of display. */
        vty_out(vty,
@@ -2079,8 +2123,9 @@ DEFUN (show_ipv6_ripng,
                                    && (rinfo->sub_type == RIPNG_ROUTE_RTE)) {
                                        len = vty_out(
                                                vty, "%s",
-                                               ifindex2ifname(rinfo->ifindex,
-                                                              ripng->vrf_id));
+                                               ifindex2ifname(
+                                                       rinfo->ifindex,
+                                                       ripng->vrf->vrf_id));
                                } else if (rinfo->metric
                                           == RIPNG_METRIC_INFINITY) {
                                        len = vty_out(vty, "kill");
@@ -2114,19 +2159,32 @@ DEFUN (show_ipv6_ripng,
 
 DEFUN (show_ipv6_ripng_status,
        show_ipv6_ripng_status_cmd,
-       "show ipv6 ripng status",
+       "show ipv6 ripng [vrf NAME] status",
        SHOW_STR
        IPV6_STR
        "Show RIPng routes\n"
+       VRF_CMD_HELP_STR
        "IPv6 routing protocol process parameters and statistics\n")
 {
        struct ripng *ripng;
-       struct vrf *vrf;
        struct interface *ifp;
+       const char *vrf_name;
+       int idx = 0;
 
-       ripng = ripng_lookup_by_vrf_id(VRF_DEFAULT);
-       if (!ripng)
+       if (argv_find(argv, argc, "vrf", &idx))
+               vrf_name = argv[idx + 1]->arg;
+       else
+               vrf_name = VRF_DEFAULT_NAME;
+
+       ripng = ripng_lookup_by_vrf_name(vrf_name);
+       if (!ripng) {
+               vty_out(vty, "%% RIPng instance not found\n");
+               return CMD_SUCCESS;
+       }
+       if (!ripng->enabled) {
+               vty_out(vty, "%% RIPng instance is disabled\n");
                return CMD_SUCCESS;
+       }
 
        vty_out(vty, "Routing Protocol is \"RIPng\"\n");
        vty_out(vty, "  Sending updates every %u seconds with +/-50%%,",
@@ -2155,8 +2213,7 @@ DEFUN (show_ipv6_ripng_status,
 
        vty_out(vty, "    Interface        Send  Recv\n");
 
-       vrf = vrf_lookup_by_id(ripng->vrf_id);
-       FOR_ALL_INTERFACES (vrf, ifp) {
+       FOR_ALL_INTERFACES (ripng->vrf, ifp) {
                struct ripng_interface *ri;
 
                ri = ifp->info;
@@ -2350,21 +2407,25 @@ void ripng_ecmp_disable(struct ripng *ripng)
 /* RIPng configuration write function. */
 static int ripng_config_write(struct vty *vty)
 {
-       struct lyd_node *dnode;
+       struct ripng *ripng;
        int write = 0;
 
-       dnode = yang_dnode_get(running_config->dnode,
-                              "/frr-ripngd:ripngd/instance");
-       if (dnode) {
-               struct ripng *ripng;
+       RB_FOREACH(ripng, ripng_instance_head, &ripng_instances) {
+               char xpath[XPATH_MAXLEN];
+               struct lyd_node *dnode;
+
+               snprintf(xpath, sizeof(xpath),
+                        "/frr-ripngd:ripngd/instance[vrf='%s']",
+                        ripng->vrf_name);
+
+               dnode = yang_dnode_get(running_config->dnode, xpath);
+               assert(dnode);
 
                nb_cli_show_dnode_cmds(vty, dnode, false);
 
-               ripng = ripng_lookup_by_vrf_id(VRF_DEFAULT);
-               if (ripng) {
-                       config_write_distribute(vty, ripng->distribute_ctx);
+               config_write_distribute(vty, ripng->distribute_ctx);
+               if (strmatch(ripng->vrf_name, VRF_DEFAULT_NAME))
                        config_write_if_rmap(vty);
-               }
 
                write = 1;
        }
@@ -2385,10 +2446,10 @@ static void ripng_distribute_update(struct distribute_ctx *ctx,
        struct access_list *alist;
        struct prefix_list *plist;
 
-       if (!dist->ifname)
+       if (!ctx->vrf || !dist->ifname)
                return;
 
-       ifp = if_lookup_by_name(dist->ifname, VRF_DEFAULT);
+       ifp = if_lookup_by_name(dist->ifname, ctx->vrf->vrf_id);
        if (ifp == NULL)
                return;
 
@@ -2437,6 +2498,8 @@ static void ripng_distribute_update(struct distribute_ctx *ctx,
 
 void ripng_distribute_update_interface(struct interface *ifp)
 {
+       struct ripng_interface *ri = ifp->info;
+       struct ripng *ripng = ri->ripng;
        struct distribute *dist;
 
        if (!ripng)
@@ -2464,56 +2527,8 @@ static void ripng_distribute_update_all_wrapper(struct access_list *notused)
 /* delete all the added ripng routes. */
 void ripng_clean(struct ripng *ripng)
 {
-       struct vrf *vrf;
-       struct interface *ifp;
-       struct agg_node *rp;
-
-       /* Clear RIPng routes */
-       for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) {
-               struct ripng_aggregate *aggregate;
-               struct list *list;
-
-               if ((list = rp->info) != NULL) {
-                       struct ripng_info *rinfo;
-                       struct listnode *listnode;
-
-                       rinfo = listgetdata(listhead(list));
-                       if (ripng_route_rte(rinfo))
-                               ripng_zebra_ipv6_delete(ripng, rp);
-
-                       for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
-                               RIPNG_TIMER_OFF(rinfo->t_timeout);
-                               RIPNG_TIMER_OFF(rinfo->t_garbage_collect);
-                               ripng_info_free(rinfo);
-                       }
-                       list_delete(&list);
-                       rp->info = NULL;
-                       agg_unlock_node(rp);
-               }
-
-               if ((aggregate = rp->aggregate) != NULL) {
-                       ripng_aggregate_free(aggregate);
-                       rp->aggregate = NULL;
-                       agg_unlock_node(rp);
-               }
-       }
-
-       /* Cancel the RIPng timers */
-       RIPNG_TIMER_OFF(ripng->t_update);
-       RIPNG_TIMER_OFF(ripng->t_triggered_update);
-       RIPNG_TIMER_OFF(ripng->t_triggered_interval);
-
-       /* Cancel the read thread */
-       if (ripng->t_read) {
-               thread_cancel(ripng->t_read);
-               ripng->t_read = NULL;
-       }
-
-       /* Close the RIPng socket */
-       if (ripng->sock >= 0) {
-               close(ripng->sock);
-               ripng->sock = -1;
-       }
+       if (ripng->enabled)
+               ripng_instance_disable(ripng);
 
        for (int i = 0; i < ZEBRA_ROUTE_MAX; i++)
                if (ripng->route_map[i].name)
@@ -2535,16 +2550,8 @@ void ripng_clean(struct ripng *ripng)
        ripng_interface_clean(ripng);
        ripng_redistribute_clean(ripng);
 
-       vrf = vrf_lookup_by_id(ripng->vrf_id);
-       vrf->info = NULL;
-
-       FOR_ALL_INTERFACES (vrf, ifp) {
-               struct ripng_interface *ri;
-
-               ri = ifp->info;
-               ri->ripng = NULL;
-       }
-
+       RB_REMOVE(ripng_instance_head, &ripng_instances, ripng);
+       XFREE(MTYPE_RIPNG_VRF_NAME, ripng->vrf_name);
        XFREE(MTYPE_RIPNG, ripng);
 }
 
@@ -2611,6 +2618,181 @@ static void ripng_routemap_update(const char *unused)
                ripng_routemap_update_redistribute(ripng);
 }
 
+/* Link RIPng instance to VRF. */
+static void ripng_vrf_link(struct ripng *ripng, struct vrf *vrf)
+{
+       struct interface *ifp;
+
+       ripng->vrf = vrf;
+       ripng->distribute_ctx->vrf = vrf;
+       vrf->info = ripng;
+
+       FOR_ALL_INTERFACES (vrf, ifp)
+               ripng_interface_sync(ifp);
+}
+
+/* Unlink RIPng instance from VRF. */
+static void ripng_vrf_unlink(struct ripng *ripng, struct vrf *vrf)
+{
+       struct interface *ifp;
+
+       ripng->vrf = NULL;
+       ripng->distribute_ctx->vrf = NULL;
+       vrf->info = NULL;
+
+       FOR_ALL_INTERFACES (vrf, ifp)
+               ripng_interface_sync(ifp);
+}
+
+static void ripng_instance_enable(struct ripng *ripng, struct vrf *vrf,
+                                 int sock)
+{
+       ripng->sock = sock;
+
+       ripng_vrf_link(ripng, vrf);
+       ripng->enabled = true;
+
+       /* Create read and timer thread. */
+       ripng_event(ripng, RIPNG_READ, ripng->sock);
+       ripng_event(ripng, RIPNG_UPDATE_EVENT, 1);
+
+       ripng_zebra_vrf_register(vrf);
+}
+
+static void ripng_instance_disable(struct ripng *ripng)
+{
+       struct vrf *vrf = ripng->vrf;
+       struct agg_node *rp;
+
+       /* Clear RIPng routes */
+       for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) {
+               struct ripng_aggregate *aggregate;
+               struct list *list;
+
+               if ((list = rp->info) != NULL) {
+                       struct ripng_info *rinfo;
+                       struct listnode *listnode;
+
+                       rinfo = listgetdata(listhead(list));
+                       if (ripng_route_rte(rinfo))
+                               ripng_zebra_ipv6_delete(ripng, rp);
+
+                       for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
+                               RIPNG_TIMER_OFF(rinfo->t_timeout);
+                               RIPNG_TIMER_OFF(rinfo->t_garbage_collect);
+                               ripng_info_free(rinfo);
+                       }
+                       list_delete(&list);
+                       rp->info = NULL;
+                       agg_unlock_node(rp);
+               }
+
+               if ((aggregate = rp->aggregate) != NULL) {
+                       ripng_aggregate_free(aggregate);
+                       rp->aggregate = NULL;
+                       agg_unlock_node(rp);
+               }
+       }
+
+       /* Cancel the RIPng timers */
+       RIPNG_TIMER_OFF(ripng->t_update);
+       RIPNG_TIMER_OFF(ripng->t_triggered_update);
+       RIPNG_TIMER_OFF(ripng->t_triggered_interval);
+
+       /* Cancel the read thread */
+       if (ripng->t_read) {
+               thread_cancel(ripng->t_read);
+               ripng->t_read = NULL;
+       }
+
+       /* Close the RIPng socket */
+       if (ripng->sock >= 0) {
+               close(ripng->sock);
+               ripng->sock = -1;
+       }
+
+       /* Clear existing peers. */
+       list_delete_all_node(ripng->peer_list);
+
+       ripng_zebra_vrf_deregister(vrf);
+
+       ripng_vrf_unlink(ripng, vrf);
+       ripng->enabled = false;
+}
+
+static int ripng_vrf_new(struct vrf *vrf)
+{
+       if (IS_RIPNG_DEBUG_EVENT)
+               zlog_debug("%s: VRF created: %s(%u)", __func__, vrf->name,
+                          vrf->vrf_id);
+
+       return 0;
+}
+
+static int ripng_vrf_delete(struct vrf *vrf)
+{
+       if (IS_RIPNG_DEBUG_EVENT)
+               zlog_debug("%s: VRF deleted: %s(%u)", __func__, vrf->name,
+                          vrf->vrf_id);
+
+       return 0;
+}
+
+static int ripng_vrf_enable(struct vrf *vrf)
+{
+       struct ripng *ripng;
+       int socket;
+
+       ripng = ripng_lookup_by_vrf_name(vrf->name);
+       if (!ripng || ripng->enabled)
+               return 0;
+
+       if (IS_RIPNG_DEBUG_EVENT)
+               zlog_debug("%s: VRF %s(%u) enabled", __func__, vrf->name,
+                          vrf->vrf_id);
+
+       /* Activate the VRF RIPng instance. */
+       if (!ripng->enabled) {
+               socket = ripng_make_socket(vrf);
+               if (socket < 0)
+                       return -1;
+
+               ripng_instance_enable(ripng, vrf, socket);
+       }
+
+       return 0;
+}
+
+static int ripng_vrf_disable(struct vrf *vrf)
+{
+       struct ripng *ripng;
+
+       ripng = ripng_lookup_by_vrf_name(vrf->name);
+       if (!ripng || !ripng->enabled)
+               return 0;
+
+       if (IS_RIPNG_DEBUG_EVENT)
+               zlog_debug("%s: VRF %s(%u) disabled", __func__, vrf->name,
+                          vrf->vrf_id);
+
+       /* Deactivate the VRF RIPng instance. */
+       if (ripng->enabled)
+               ripng_instance_disable(ripng);
+
+       return 0;
+}
+
+void ripng_vrf_init(void)
+{
+       vrf_init(ripng_vrf_new, ripng_vrf_enable, ripng_vrf_disable,
+                ripng_vrf_delete, NULL);
+}
+
+void ripng_vrf_terminate(void)
+{
+       vrf_terminate();
+}
+
 /* Initialize ripng structure and set commands. */
 void ripng_init()
 {
index 95039bf57961a398de80cc85d223193581bd4178..e9894dd4cf5bb8398f75ff2d315988695c41389c 100644 (file)
 
 /* RIPng structure. */
 struct ripng {
-       /* VRF ID. */
-       vrf_id_t vrf_id;
+       RB_ENTRY(ripng) entry;
+
+       /* VRF this routing instance is associated with. */
+       char *vrf_name;
+
+       /* VRF backpointer (might be NULL if the VRF doesn't exist). */
+       struct vrf *vrf;
+
+       /* Status of the routing instance. */
+       bool enabled;
 
        /* RIPng socket. */
        int sock;
@@ -152,6 +160,8 @@ struct ripng {
        /* For distribute-list container */
        struct distribute_ctx *distribute_ctx;
 };
+RB_HEAD(ripng_instance_head, ripng);
+RB_PROTOTYPE(ripng_instance_head, ripng, entry, ripng_instance_compare)
 
 /* Routing table entry. */
 struct rte {
@@ -378,6 +388,8 @@ extern int ripng_passive_interface_unset(struct ripng *ripng,
 extern void ripng_passive_interface_clean(struct ripng *ripng);
 extern void ripng_if_init(void);
 extern void ripng_route_map_init(void);
+extern void ripng_zebra_vrf_register(struct vrf *vrf);
+extern void ripng_zebra_vrf_deregister(struct vrf *vrf);
 extern void ripng_terminate(void);
 /* zclient_init() is done by ripng_zebra.c:zebra_init() */
 extern void zebra_init(struct thread_master *);
@@ -459,10 +471,15 @@ extern int ripng_interface_address_add(int command, struct zclient *,
                                       zebra_size_t, vrf_id_t);
 extern int ripng_interface_address_delete(int command, struct zclient *,
                                          zebra_size_t, vrf_id_t);
+extern int ripng_interface_vrf_update(int command, struct zclient *zclient,
+                                     zebra_size_t length, vrf_id_t vrf_id);
+extern void ripng_interface_sync(struct interface *ifp);
 
 extern struct ripng *ripng_lookup_by_vrf_id(vrf_id_t vrf_id);
-extern struct ripng *ripng_create(struct vrf *vrf, int socket);
-extern int ripng_make_socket(void);
+extern struct ripng *ripng_lookup_by_vrf_name(const char *vrf_name);
+extern struct ripng *ripng_create(const char *vrf_name, struct vrf *vrf,
+                                 int socket);
+extern int ripng_make_socket(struct vrf *vrf);
 extern int ripng_network_write(struct vty *vty, struct ripng *ripng);
 
 extern struct ripng_info *ripng_ecmp_add(struct ripng *ripng,
@@ -472,6 +489,9 @@ extern struct ripng_info *ripng_ecmp_replace(struct ripng *ripng,
 extern struct ripng_info *ripng_ecmp_delete(struct ripng *ripng,
                                            struct ripng_info *rinfo);
 
+extern void ripng_vrf_init(void);
+extern void ripng_vrf_terminate(void);
+
 /* Northbound. */
 extern void ripng_cli_init(void);
 extern const struct frr_yang_module_info frr_ripngd_info;
index 11be03363ca29ab6a778eb51b714eca62d41bfa0..41bc50670feccb9dd0df1ecd9840007b4e4f2822 100644 (file)
@@ -1526,8 +1526,8 @@ DEFUNSH(VTYSH_RIPD, router_rip, router_rip_cmd, "router rip [vrf NAME]",
        return CMD_SUCCESS;
 }
 
-DEFUNSH(VTYSH_RIPNGD, router_ripng, router_ripng_cmd, "router ripng",
-       ROUTER_STR "RIPng\n")
+DEFUNSH(VTYSH_RIPNGD, router_ripng, router_ripng_cmd, "router ripng [vrf NAME]",
+       ROUTER_STR "RIPng\n" VRF_CMD_HELP_STR)
 {
        vty->node = RIPNG_NODE;
        return CMD_SUCCESS;
index 0cc5f18a5f6d3535cd30945557d3d1cbbfc4ca50..5d6d61564f983ff78c8a250d690b76e8160093d7 100644 (file)
@@ -33,13 +33,18 @@ module frr-ripngd {
 
   container ripngd {
     /*
-     * Global configuration data
+     * Routing instance configuration.
      */
-    container instance {
-      presence "Present if the RIPng protocol is enabled.";
+    list instance {
+      key "vrf";
       description
         "RIPng routing instance.";
 
+      leaf vrf {
+        type string;
+        description
+          "VRF name.";
+      }
       leaf allow-ecmp {
         type boolean;
         default "false";