summaryrefslogtreecommitdiff
path: root/zebra/zserv.c
diff options
context:
space:
mode:
authorvivek <vivek@cumulusnetworks.com>2016-02-25 19:30:53 +0000
committervivek <vivek@cumulusnetworks.com>2016-02-25 19:30:53 +0000
commitc8e264b60e405e60b666cca62d5c96c20a9cf3bd (patch)
tree85f3ad0f6bf667d1ddb04a5330fe51bb1bc3d1e4 /zebra/zserv.c
parentb47b0a8480cbbfa30de4794f149f39ca8ad43921 (diff)
Quagga: Implement VRF change semantics for an interface
Implement VRF change semantics for an interface to be invoked when an interface is moved from one VRF (e.g., the Default) to another. This includes the message definition as well as updating, deleting or adding the interface from clients, depending on their interest in the VRFs (old and new). Also handle replay of the addresses on the interface upon VRF change, if required. Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com> Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com> Reviewed-by: Don Slice <dslice@cumulusnetworks.com> Ticket: CM-9527 Reviewed By: CCR-4174 Testing Done: Manual tests of various scenarios
Diffstat (limited to 'zebra/zserv.c')
-rw-r--r--zebra/zserv.c76
1 files changed, 58 insertions, 18 deletions
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 3f9eceae15..6603437f09 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -357,7 +357,7 @@ zsend_interface_nbr_address (int cmd, struct zserv *client,
struct prefix *p;
/* Check this client need interface information. */
- if (! client->ifinfo)
+ if (! vrf_bitmap_check (client->ifinfo, ifp->vrf_id))
return 0;
s = client->obuf;
@@ -433,6 +433,61 @@ zebra_interface_nbr_address_delete_update (struct interface *ifp,
zsend_interface_nbr_address (ZEBRA_INTERFACE_NBR_ADDRESS_DELETE, client, ifp, ifc);
}
+/* Send addresses on interface to client */
+int
+zsend_interface_addresses (struct zserv *client, struct interface *ifp)
+{
+ struct listnode *cnode, *cnnode;
+ struct connected *c;
+ struct nbr_connected *nc;
+
+ /* Send interface addresses. */
+ for (ALL_LIST_ELEMENTS (ifp->connected, cnode, cnnode, c))
+ {
+ if (!CHECK_FLAG (c->conf, ZEBRA_IFC_REAL))
+ continue;
+
+ if (zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_ADD, client,
+ ifp, c) < 0)
+ return -1;
+ }
+
+ /* Send interface neighbors. */
+ for (ALL_LIST_ELEMENTS (ifp->nbr_connected, cnode, cnnode, nc))
+ {
+ if (zsend_interface_nbr_address (ZEBRA_INTERFACE_NBR_ADDRESS_ADD,
+ client, ifp, nc) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Notify client about interface moving from one VRF to another.
+ * Whether client is interested in old and new VRF is checked by caller.
+ */
+int
+zsend_interface_vrf_update (struct zserv *client, struct interface *ifp,
+ vrf_id_t vrf_id)
+{
+ struct stream *s;
+
+ s = client->obuf;
+ stream_reset (s);
+
+ zserv_create_header (s, ZEBRA_INTERFACE_VRF_UPDATE, ifp->vrf_id);
+
+ /* Fill in the ifIndex of the interface and its new VRF (id) */
+ stream_putl (s, ifp->ifindex);
+ stream_putw (s, vrf_id);
+
+ /* Write packet size. */
+ stream_putw_at (s, 0, stream_get_endp (s));
+
+ client->if_vrfchg_cnt++;
+ return zebra_server_send_message(client);
+}
+
/* Add new nbr connected IPv6 address if none exists already, or replace the
existing one if an ifc entry is found on the interface. */
void
@@ -1030,10 +1085,7 @@ static int
zread_interface_add (struct zserv *client, u_short length, vrf_id_t vrf_id)
{
struct listnode *ifnode, *ifnnode;
- struct listnode *cnode, *cnnode;
struct interface *ifp;
- struct connected *c;
- struct nbr_connected *nc;
/* Interface information is needed. */
vrf_bitmap_set (client->ifinfo, vrf_id);
@@ -1047,20 +1099,8 @@ zread_interface_add (struct zserv *client, u_short length, vrf_id_t vrf_id)
if (zsend_interface_add (client, ifp) < 0)
return -1;
- for (ALL_LIST_ELEMENTS (ifp->connected, cnode, cnnode, c))
- {
- if (CHECK_FLAG (c->conf, ZEBRA_IFC_REAL) &&
- (zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_ADD, client,
- ifp, c) < 0))
- return -1;
- }
- for (ALL_LIST_ELEMENTS (ifp->nbr_connected, cnode, cnnode, nc))
- {
- if (zsend_interface_nbr_address (ZEBRA_INTERFACE_NBR_ADDRESS_ADD, client,
- ifp, nc) < 0)
- return -1;
- }
-
+ if (zsend_interface_addresses (client, ifp) < 0)
+ return -1;
}
return 0;
}