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/redistribute.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/redistribute.c')
| -rw-r--r-- | zebra/redistribute.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 552524dbc8..9930285199 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -558,6 +558,74 @@ zebra_interface_address_delete_update (struct interface *ifp, } } +/* Interface VRF change. May need to delete from clients not interested in + * the new VRF. Note that this function is invoked *prior* to the VRF change. + */ +void +zebra_interface_vrf_update_del (struct interface *ifp, vrf_id_t new_vrf_id) +{ + struct listnode *node, *nnode; + struct zserv *client; + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug ("MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/DEL %s VRF Id %u -> %u", + ifp->name, ifp->vrf_id, new_vrf_id); + + for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) + { + /* Skip clients not interested in both VRFs. */ + if (!vrf_bitmap_check (client->ifinfo, ifp->vrf_id) && + !vrf_bitmap_check (client->ifinfo, new_vrf_id)) + continue; + + if (!vrf_bitmap_check (client->ifinfo, new_vrf_id)) + { + /* Need to delete if the client is not interested in the new VRF. */ + zsend_interface_update (ZEBRA_INTERFACE_DOWN, client, ifp); + client->ifdel_cnt++; + zsend_interface_delete (client, ifp); + } + else if (vrf_bitmap_check (client->ifinfo, ifp->vrf_id)) + { + /* Client is interested in both VRFs, inform about the change. */ + zsend_interface_vrf_update (client, ifp, new_vrf_id); + } + } +} + +/* Interface VRF change. This function is invoked *post* VRF change and sends an + * add to clients who are interested in the new VRF but not in the old VRF. + */ +void +zebra_interface_vrf_update_add (struct interface *ifp, vrf_id_t old_vrf_id) +{ + struct listnode *node, *nnode; + struct zserv *client; + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug ("MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/ADD %s VRF Id %u -> %u", + ifp->name, old_vrf_id, ifp->vrf_id); + + for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) + { + /* Skip clients interested in both VRFs - they would've got an Update. */ + if (vrf_bitmap_check (client->ifinfo, ifp->vrf_id) && + vrf_bitmap_check (client->ifinfo, old_vrf_id)) + continue; + + /* Skip clients not interested in the new VRF - they would've + * got a Delete. + */ + if (!vrf_bitmap_check (client->ifinfo, ifp->vrf_id)) + continue; + + /* Need to add if the client is interested in the new VRF. */ + client->ifadd_cnt++; + zsend_interface_add (client, ifp); + zsend_interface_addresses (client, ifp); + } +} + int zebra_add_import_table_entry (struct route_node *rn, struct rib *rib) { |
