diff options
| author | vivek <vivek@cumulusnetworks.com> | 2016-02-25 19:30:53 +0000 |
|---|---|---|
| committer | vivek <vivek@cumulusnetworks.com> | 2016-02-25 19:30:53 +0000 |
| commit | c8e264b60e405e60b666cca62d5c96c20a9cf3bd (patch) | |
| tree | 85f3ad0f6bf667d1ddb04a5330fe51bb1bc3d1e4 /zebra/zserv.c | |
| parent | b47b0a8480cbbfa30de4794f149f39ca8ad43921 (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.c | 76 |
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; } |
