diff options
Diffstat (limited to 'pbrd')
| -rw-r--r-- | pbrd/pbr_event.c | 220 | ||||
| -rw-r--r-- | pbrd/pbr_event.h | 137 | ||||
| -rw-r--r-- | pbrd/pbr_main.c | 3 | ||||
| -rw-r--r-- | pbrd/pbr_map.c | 301 | ||||
| -rw-r--r-- | pbrd/pbr_map.h | 17 | ||||
| -rw-r--r-- | pbrd/pbr_nht.c | 289 | ||||
| -rw-r--r-- | pbrd/pbr_nht.h | 10 | ||||
| -rw-r--r-- | pbrd/pbr_vty.c | 65 | ||||
| -rw-r--r-- | pbrd/pbr_zebra.c | 68 | ||||
| -rw-r--r-- | pbrd/pbr_zebra.h | 5 | ||||
| -rw-r--r-- | pbrd/subdir.am | 2 |
11 files changed, 378 insertions, 739 deletions
diff --git a/pbrd/pbr_event.c b/pbrd/pbr_event.c deleted file mode 100644 index 4563d7d91c..0000000000 --- a/pbrd/pbr_event.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * PBR-event Code - * Copyright (C) 2018 Cumulus Networks, Inc. - * Donald Sharp - * - * This file is part of FRR. - * - * FRR is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * FRR is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; see the file COPYING; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include <zebra.h> - -#include <thread.h> -#include <workqueue.h> -#include <nexthop.h> -#include <log.h> -#include <vty.h> - -#include "pbrd/pbr_event.h" -#include "pbrd/pbr_map.h" -#include "pbrd/pbr_nht.h" -#include "pbrd/pbr_memory.h" -#include "pbrd/pbr_debug.h" - -DEFINE_MTYPE_STATIC(PBRD, PBR_EVENT, "Event WorkQueue") - -struct work_queue *pbr_event_wq; - -static const char *pbr_event_wqentry2str(struct pbr_event *pbre, - char *buffer, size_t buflen) -{ - switch (pbre->event) { - case PBR_NHG_NEW: - snprintf(buffer, buflen, "Nexthop Group Added %s", - pbre->name); - break; - case PBR_NHG_ADD_NEXTHOP: - snprintf(buffer, buflen, "Nexthop Group Nexthop Added %s", - pbre->name); - break; - case PBR_NHG_DEL_NEXTHOP: - snprintf(buffer, buflen, "Nexthop Group Nexthop Deleted %s", - pbre->name); - break; - case PBR_NHG_DELETE: - snprintf(buffer, buflen, "Nexthop Group Deleted %s", - pbre->name); - break; - case PBR_MAP_NEXTHOP_ADD: - snprintf(buffer, buflen, "Nexthop Added to %s(%d)", pbre->name, - pbre->seqno); - break; - case PBR_MAP_NEXTHOP_DELETE: - snprintf(buffer, buflen, "Nexthop Deleted from %s(%d)", - pbre->name, pbre->seqno); - break; - case PBR_MAP_NHG_ADD: - snprintf(buffer, buflen, "Nexthop Group Added to %s(%d)", - pbre->name, pbre->seqno); - break; - case PBR_MAP_NHG_DELETE: - snprintf(buffer, buflen, "Nexthop Group Deleted from %s(%d)", - pbre->name, pbre->seqno); - break; - case PBR_MAP_ADD: - snprintf(buffer, buflen, "PBR-MAP %s Added", - pbre->name); - break; - case PBR_MAP_MODIFY: - snprintf(buffer, buflen, "PBR_MAP %s Modified", - pbre->name); - break; - case PBR_MAP_DELETE: - snprintf(buffer, buflen, "PBR_MAP %s Deleted", - pbre->name); - break; - case PBR_NH_CHANGED: - snprintf(buffer, buflen, "Nexthop Call back from Zebra"); - break; - case PBR_MAP_INSTALL: - snprintf(buffer, buflen, "PBR_MAP %s Installing into zapi", - pbre->name); - break; - case PBR_POLICY_CHANGED: - snprintf(buffer, buflen, - "PBR-Policy %s applied to an interface", pbre->name); - break; - case PBR_MAP_POLICY_INSTALL: - snprintf(buffer, buflen, "PBR-POLICY installation time for %s", - pbre->name); - break; - case PBR_POLICY_DELETED: - snprintf(buffer, buflen, "PBR-POLICY deleted from %s", - pbre->name); - break; - } - - return buffer; -} - -void pbr_event_free(struct pbr_event **pbre) -{ - XFREE(MTYPE_PBR_EVENT, *pbre); -} - -static void pbr_event_delete_wq(struct work_queue *wq, void *data) -{ - struct pbr_event *pbre = (struct pbr_event *)data; - - XFREE(MTYPE_PBR_EVENT, pbre); -} - -static wq_item_status pbr_event_process_wq(struct work_queue *wq, void *data) -{ - struct pbr_event *pbre = (struct pbr_event *)data; - char buffer[256]; - - DEBUGD(&pbr_dbg_event, "%s: Handling event %s", __PRETTY_FUNCTION__, - pbr_event_wqentry2str(pbre, buffer, sizeof(buffer))); - - switch (pbre->event) { - case PBR_NHG_NEW: - pbr_nht_add_group(pbre->name); - pbr_map_check_nh_group_change(pbre->name); - break; - case PBR_NHG_ADD_NEXTHOP: - pbr_nht_change_group(pbre->name); - pbr_map_check_nh_group_change(pbre->name); - break; - case PBR_NHG_DEL_NEXTHOP: - pbr_nht_change_group(pbre->name); - pbr_map_check_nh_group_change(pbre->name); - break; - case PBR_NHG_DELETE: - pbr_nht_delete_group(pbre->name); - pbr_map_check_nh_group_change(pbre->name); - break; - case PBR_MAP_NEXTHOP_ADD: - pbr_nht_add_individual_nexthop(pbre->name, pbre->seqno); - pbr_map_check(pbre->name, pbre->seqno); - break; - case PBR_MAP_NEXTHOP_DELETE: - pbr_nht_delete_individual_nexthop(pbre->name, pbre->seqno); - pbr_map_check(pbre->name, pbre->seqno); - break; - case PBR_MAP_NHG_ADD: - pbr_map_check(pbre->name, pbre->seqno); - break; - case PBR_MAP_NHG_DELETE: - pbr_map_check(pbre->name, pbre->seqno); - break; - case PBR_MAP_ADD: - pbr_map_add_interfaces(pbre->name); - break; - case PBR_MAP_MODIFY: - pbr_map_check(pbre->name, pbre->seqno); - break; - case PBR_MAP_DELETE: - pbr_map_delete(pbre->name, pbre->seqno); - break; - case PBR_NH_CHANGED: - pbr_map_check_nh_group_change(pbre->name); - break; - case PBR_MAP_INSTALL: - pbr_map_install(pbre->name); - break; - case PBR_POLICY_CHANGED: - pbr_map_check_policy_change(pbre->name); - break; - case PBR_MAP_POLICY_INSTALL: - pbr_map_policy_install(pbre->name); - break; - case PBR_POLICY_DELETED: - pbr_map_policy_delete(pbre->name); - break; - } - - return WQ_SUCCESS; -} - -void pbr_event_enqueue(struct pbr_event *pbre) -{ - work_queue_add(pbr_event_wq, pbre); -} - -struct pbr_event *pbr_event_new(enum pbr_events ev, const char *name) -{ - struct pbr_event *event; - - event = XCALLOC(MTYPE_PBR_EVENT, sizeof(struct pbr_event)); - event->event = ev; - if (name) - strlcpy(event->name, name, sizeof(event->name)); - return event; -} - -extern struct thread_master *master; - -void pbr_event_init(void) -{ - pbr_event_wq = work_queue_new(master, "PBR Main Work Queue"); - pbr_event_wq->spec.workfunc = &pbr_event_process_wq; - pbr_event_wq->spec.del_item_data = &pbr_event_delete_wq; -} - -void pbr_event_stop(void) -{ - work_queue_free_and_null(&pbr_event_wq); -} diff --git a/pbrd/pbr_event.h b/pbrd/pbr_event.h deleted file mode 100644 index 2d895d9694..0000000000 --- a/pbrd/pbr_event.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * PBR-event Header - * Copyright (C) 2018 Cumulus Networks, Inc. - * Donald Sharp - * - * This file is part of FRR. - * - * FRR is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * FRR is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; see the file COPYING; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -#ifndef __PBR_EVENT_H__ -#define __PBR_EVENT_H__ - -enum pbr_events { - /* - * A NHG has been added to the system, handle it - */ - PBR_NHG_NEW, - - /* - * A NHG has been modified( added a new nexthop ) - */ - PBR_NHG_ADD_NEXTHOP, - - /* - * A NHG has been modified( deleted a nexthop ) - */ - PBR_NHG_DEL_NEXTHOP, - - /* - * A NHG has been deleted from the system - */ - PBR_NHG_DELETE, - - /* - * A individual nexthop has been added - */ - PBR_MAP_NEXTHOP_ADD, - - /* - * A individual nexthop has been deleted - */ - PBR_MAP_NEXTHOP_DELETE, - - /* - * A nexthop group has been added to a pbr-map - */ - PBR_MAP_NHG_ADD, - - /* - * A nexthop group has been deleted from a pbr-map - */ - PBR_MAP_NHG_DELETE, - - /* - * A new pbr-map has been created - */ - PBR_MAP_ADD, - - /* - * The pbr-map has been modified in some fashion - */ - PBR_MAP_MODIFY, - - /* - * The pbr-map has been deleted from the system - */ - PBR_MAP_DELETE, - - /* - * Start the sequence of events to install/remove the policy - * from being installed - */ - PBR_MAP_INSTALL, - - /* - * We believe we have gotten enough information to actually - * install the rule portion, since the nexthops are installed - */ - PBR_MAP_POLICY_INSTALL, - - /* - * Callbacks for a Nexthop in a nexthop group has been - * changed in some fashion - */ - PBR_NH_CHANGED, - - /* - * Callback for when a policy has been applied to an interface - */ - PBR_POLICY_CHANGED, - - /* - * Callback for when a interface has been issued a no - * policy command - */ - PBR_POLICY_DELETED, -}; - -struct pbr_event { - enum pbr_events event; - - char name[100]; - union g_addr addr; - uint32_t seqno; -}; - -/* - * Return a event structure that can be filled in and enqueued. - * Assume this memory is owned by the event subsystem. - */ -extern struct pbr_event *pbr_event_new(enum pbr_events ev, const char *name); - -/* - * Free the associated pbr_event item - */ -extern void pbr_event_free(struct pbr_event **pbre); - -/* - * Enqueue an event for later processing - */ -void pbr_event_enqueue(struct pbr_event *pbre); - -extern void pbr_event_init(void); -extern void pbr_event_stop(void); -#endif diff --git a/pbrd/pbr_main.c b/pbrd/pbr_main.c index 83cac6daa2..638e284a1a 100644 --- a/pbrd/pbr_main.c +++ b/pbrd/pbr_main.c @@ -46,7 +46,6 @@ #include "pbr_nht.h" #include "pbr_map.h" #include "pbr_zebra.h" -#include "pbr_event.h" #include "pbr_vty.h" #include "pbr_debug.h" @@ -82,7 +81,6 @@ static void sigint(void) { zlog_notice("Terminating on signal"); - pbr_event_stop(); exit(0); } @@ -154,7 +152,6 @@ int main(int argc, char **argv, char **envp) pbr_nhgroup_del_nexthop_cb, pbr_nhgroup_delete_cb); - pbr_event_init(); pbr_nht_init(); pbr_map_init(); pbr_zebra_init(); diff --git a/pbrd/pbr_map.c b/pbrd/pbr_map.c index 3b058675d7..8e4d52cbcf 100644 --- a/pbrd/pbr_map.c +++ b/pbrd/pbr_map.c @@ -32,7 +32,6 @@ #include "pbr_nht.h" #include "pbr_map.h" -#include "pbr_event.h" #include "pbr_zebra.h" #include "pbr_memory.h" #include "pbr_debug.h" @@ -84,9 +83,20 @@ static int pbr_map_interface_compare(const struct pbr_map_interface *pmi1, return strcmp(pmi1->ifp->name, pmi2->ifp->name); } -static void pbr_map_interface_list_delete(const struct pbr_map_interface *pmi) +static void pbr_map_interface_list_delete(struct pbr_map_interface *pmi) { - pbr_map_policy_delete(pmi->ifp->name); + struct pbr_map_interface *pmi_int; + struct listnode *node, *nnode; + struct pbr_map *pbrm; + + RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) { + for (ALL_LIST_ELEMENTS(pbrm->incoming, node, nnode, pmi_int)) { + if (pmi == pmi_int) { + pbr_map_policy_delete(pbrm, pmi); + return; + } + } + } } static const char *pbr_map_reason_str[] = { @@ -117,26 +127,20 @@ void pbr_map_interface_delete(struct pbr_map *pbrm, struct interface *ifp_del) struct listnode *node; struct pbr_map_interface *pmi; - struct pbr_event *pbre; for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, node, pmi)) { if (ifp_del == pmi->ifp) break; } - if (pmi) { - pmi->delete = true; - - pbre = pbr_event_new(PBR_POLICY_DELETED, pmi->ifp->name); - pbr_event_enqueue(pbre); - } + if (pmi) + pbr_map_policy_delete(pbrm, pmi); } void pbr_map_add_interface(struct pbr_map *pbrm, struct interface *ifp_add) { struct listnode *node; struct pbr_map_interface *pmi; - struct pbr_event *pbre; for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, node, pmi)) { if (ifp_add == pmi->ifp) @@ -148,8 +152,9 @@ void pbr_map_add_interface(struct pbr_map *pbrm, struct interface *ifp_add) pmi->pbrm = pbrm; listnode_add_sort(pbrm->incoming, pmi); - pbre = pbr_event_new(PBR_POLICY_CHANGED, pbrm->name); - pbr_event_enqueue(pbre); + pbr_map_check_valid(pbrm->name); + if (pbrm->valid && !pbrm->installed) + pbr_map_install(pbrm); } void pbr_map_write_interfaces(struct vty *vty, struct interface *ifp) @@ -169,35 +174,21 @@ struct pbr_map *pbrm_find(const char *name) return RB_FIND(pbr_map_entry_head, &pbr_maps, &pbrm); } -extern void pbr_map_delete(const char *name, uint32_t seqno) +extern void pbr_map_delete(struct pbr_map_sequence *pbrms) { struct pbr_map *pbrm; - struct pbr_map_sequence *pbrms; - struct listnode *node, *nnode; - bool uninstall = false; - - pbrm = pbrm_find(name); - - for (ALL_LIST_ELEMENTS(pbrm->seqnumbers, node, nnode, pbrms)) { - if (pbrms->reason & PBR_MAP_DEL_SEQUENCE_NUMBER) { - uninstall = true; - break; - } - } + struct listnode *inode; + struct pbr_map_interface *pmi; - if (uninstall) - pbr_send_pbr_map(pbrm, 0); + pbrm = pbrms->parent; - for (ALL_LIST_ELEMENTS(pbrm->seqnumbers, node, nnode, pbrms)) { - if (!(pbrms->reason & PBR_MAP_DEL_SEQUENCE_NUMBER)) - continue; + for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi)) + pbr_send_pbr_map(pbrms, pmi, false); - if (pbrms->nhg) - pbr_nht_delete_individual_nexthop(pbrms->parent->name, - pbrms->seqno); + if (pbrms->nhg) + pbr_nht_delete_individual_nexthop(pbrms); - listnode_delete(pbrm->seqnumbers, pbrms); - } + listnode_delete(pbrm->seqnumbers, pbrms); if (pbrm->seqnumbers->count == 0) { RB_REMOVE(pbr_map_entry_head, &pbr_maps, pbrm); @@ -205,6 +196,24 @@ extern void pbr_map_delete(const char *name, uint32_t seqno) } } +void pbr_map_delete_nexthop_group(struct pbr_map_sequence *pbrms) +{ + struct pbr_map *pbrm = pbrms->parent; + struct listnode *node; + struct pbr_map_interface *pmi; + + if (pbrm->valid && pbrms->nhs_installed && pbrm->incoming->count) { + for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, node, pmi)) + pbr_send_pbr_map(pbrms, pmi, false); + } + + pbrm->valid = false; + pbrms->nhs_installed = false; + pbrms->installed = false; + pbrms->reason |= PBR_MAP_INVALID_NO_NEXTHOPS; + pbrms->nhgrp_name = NULL; +} + struct pbr_map_sequence *pbrms_lookup_unique(uint32_t unique, ifindex_t ifindex) { @@ -232,12 +241,28 @@ struct pbr_map_sequence *pbrms_lookup_unique(uint32_t unique, return NULL; } +static void pbr_map_add_interfaces(struct pbr_map *pbrm) +{ + struct interface *ifp; + struct pbr_interface *pbr_ifp; + struct vrf *vrf; + + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + FOR_ALL_INTERFACES (vrf, ifp) { + if (ifp->info) { + pbr_ifp = ifp->info; + if (strcmp(pbrm->name, pbr_ifp->mapname) == 0) + pbr_map_add_interface(pbrm, ifp); + } + } + } +} + struct pbr_map_sequence *pbrms_get(const char *name, uint32_t seqno) { struct pbr_map *pbrm; struct pbr_map_sequence *pbrms; struct listnode *node; - struct pbr_event *pbre; pbrm = pbrm_find(name); if (!pbrm) { @@ -258,9 +283,8 @@ struct pbr_map_sequence *pbrms_get(const char *name, uint32_t seqno) RB_INSERT(pbr_map_entry_head, &pbr_maps, pbrm); - pbre = pbr_event_new(PBR_MAP_ADD, name); - } else - pbre = NULL; + pbr_map_add_interfaces(pbrm); + } for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) { if (pbrms->seqno == seqno) @@ -284,9 +308,6 @@ struct pbr_map_sequence *pbrms_get(const char *name, uint32_t seqno) pbrm->installed = false; } - if (pbre) - pbr_event_enqueue(pbre); - return pbrms; } @@ -375,7 +396,6 @@ bool pbr_map_check_valid(const char *name) void pbr_map_schedule_policy_from_nhg(const char *nh_group) { struct pbr_map_sequence *pbrms; - struct pbr_event *pbre; struct pbr_map *pbrm; struct listnode *node; @@ -390,11 +410,7 @@ void pbr_map_schedule_policy_from_nhg(const char *nh_group) && (strcmp(nh_group, pbrms->nhgrp_name) == 0)) { pbrms->nhs_installed = true; - pbre = pbr_event_new(PBR_MAP_MODIFY, - pbrm->name); - pbre->seqno = pbrms->seqno; - - pbr_event_enqueue(pbre); + pbr_map_check(pbrms); } if (pbrms->nhg @@ -402,11 +418,7 @@ void pbr_map_schedule_policy_from_nhg(const char *nh_group) == 0)) { pbrms->nhs_installed = true; - pbre = pbr_event_new(PBR_MAP_MODIFY, - pbrm->name); - pbre->seqno = pbrms->seqno; - - pbr_event_enqueue(pbre); + pbr_map_check(pbrms); } } } @@ -416,49 +428,41 @@ void pbr_map_policy_install(const char *name) { struct pbr_map_sequence *pbrms; struct pbr_map *pbrm; - struct listnode *node; - bool install; + struct listnode *node, *inode; + struct pbr_map_interface *pmi; DEBUGD(&pbr_dbg_map, "%s: for %s", __PRETTY_FUNCTION__, name); pbrm = pbrm_find(name); if (!pbrm) return; - install = true; for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) { DEBUGD(&pbr_dbg_map, "%s: Looking at what to install %s(%u) %d %d", __PRETTY_FUNCTION__, name, pbrms->seqno, pbrm->valid, pbrms->nhs_installed); - if (!pbrm->valid || !pbrms->nhs_installed) - install = false; - } - if (install && pbrm->incoming->count) { - DEBUGD(&pbr_dbg_map, "\tInstalling"); - pbr_send_pbr_map(pbrm, true); + if (pbrm->valid && pbrms->nhs_installed && pbrm->incoming->count) { + DEBUGD(&pbr_dbg_map, "\tInstalling %s %u", + pbrm->name, pbrms->seqno); + for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi)) + pbr_send_pbr_map(pbrms, pmi, true); + } } } -void pbr_map_policy_delete(const char *ifname) +void pbr_map_policy_delete(struct pbr_map *pbrm, struct pbr_map_interface *pmi) { - struct listnode *node, *nnode; - struct pbr_map_interface *pmi; - struct pbr_map *pbrm; + struct listnode *node; + struct pbr_map_sequence *pbrms; - RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) { - for (ALL_LIST_ELEMENTS(pbrm->incoming, node, nnode, pmi)) { - DEBUGD(&pbr_dbg_map, "Comparing %s to %s %d", - pmi->ifp->name, ifname, pmi->delete); - if (strcmp(ifname, pmi->ifp->name) != 0) - continue; - pbr_send_pbr_map(pbrm, false); - listnode_delete(pbrm->incoming, pmi); - pmi->pbrm = NULL; - XFREE(MTYPE_PBR_MAP_INTERFACE, pmi); - } - } + for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) + pbr_send_pbr_map(pbrms, pmi, false); + + listnode_delete(pbrm->incoming, pmi); + pmi->pbrm = NULL; + XFREE(MTYPE_PBR_MAP_INTERFACE, pmi); } /* @@ -490,133 +494,64 @@ void pbr_map_check_nh_group_change(const char *nh_group) pbr_map_check_valid_internal(pbrm); - if (original != pbrm->valid) { - struct pbr_event *pbre; - - pbre = pbr_event_new(PBR_MAP_INSTALL, - pbrm->name); - pbr_event_enqueue(pbre); - } + if (original != pbrm->valid) + pbr_map_install(pbrm); break; } } } } -void pbr_map_check(const char *name, uint32_t seqno) +void pbr_map_check(struct pbr_map_sequence *pbrms) { - struct pbr_map_sequence *pbrms; - struct listnode *node; struct pbr_map *pbrm; + struct listnode *inode; + struct pbr_map_interface *pmi; + bool install; - DEBUGD(&pbr_dbg_map, "%s: for %s(%u)", __PRETTY_FUNCTION__, name, - seqno); - if (pbr_map_check_valid(name)) - DEBUGD(&pbr_dbg_map, "We are totally valid %s\n", name); - - pbrm = pbrm_find(name); - if (!pbrm) - return; + pbrm = pbrms->parent; + DEBUGD(&pbr_dbg_map, "%s: for %s(%u)", __PRETTY_FUNCTION__, + pbrm->name, pbrms->seqno); + if (pbr_map_check_valid(pbrm->name)) + DEBUGD(&pbr_dbg_map, "We are totally valid %s\n", + pbrm->name); - for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) { - if (seqno != pbrms->seqno) - continue; + DEBUGD(&pbr_dbg_map, "%s: Installing %s(%u) reason: %" PRIu64, + __PRETTY_FUNCTION__, pbrm->name, pbrms->seqno, pbrms->reason); + if (pbrms->reason == PBR_MAP_VALID_SEQUENCE_NUMBER) { + install = true; DEBUGD(&pbr_dbg_map, "%s: Installing %s(%u) reason: %" PRIu64, - __PRETTY_FUNCTION__, name, seqno, pbrms->reason); - - if (pbrms->reason == PBR_MAP_VALID_SEQUENCE_NUMBER) { - struct pbr_event *pbre; - - DEBUGD(&pbr_dbg_map, - "%s: Installing %s(%u) reason: %" PRIu64, - __PRETTY_FUNCTION__, name, seqno, pbrms->reason); - DEBUGD(&pbr_dbg_map, - "\tSending PBR_MAP_POLICY_INSTALL event"); - - pbre = pbr_event_new(PBR_MAP_POLICY_INSTALL, - pbrm->name); - pbre->event = PBR_MAP_POLICY_INSTALL; - strcpy(pbre->name, pbrm->name); - - pbr_event_enqueue(pbre); - - break; - } else { - DEBUGD(&pbr_dbg_map, - "%s: Removing %s(%u) reason: %" PRIu64, - __PRETTY_FUNCTION__, name, seqno, pbrms->reason); - pbr_send_pbr_map(pbrm, false); - break; - } - } -} - -void pbr_map_install(const char *name) -{ - struct pbr_map *pbrm; - - pbrm = pbrm_find(name); - if (!pbrm) { + __PRETTY_FUNCTION__, pbrm->name, pbrms->seqno, + pbrms->reason); DEBUGD(&pbr_dbg_map, - "%s: Specified PBR-MAP(%s) does not exist?", - __PRETTY_FUNCTION__, name); - return; - } - - if (!pbrm->incoming->count) - return; - - pbr_send_pbr_map(pbrm, true); - pbrm->installed = true; -} - -void pbr_map_add_interfaces(const char *name) -{ - struct pbr_map *pbrm; - struct interface *ifp; - struct pbr_interface *pbr_ifp; - struct vrf *vrf; - - pbrm = pbrm_find(name); - if (!pbrm) { + "\tSending PBR_MAP_POLICY_INSTALL event"); + } else { + install = false; DEBUGD(&pbr_dbg_map, - "%s: Specified PBR-MAP(%s) does not exist?", - __PRETTY_FUNCTION__, name); - return; + "%s: Removing %s(%u) reason: %" PRIu64, + __PRETTY_FUNCTION__, pbrm->name, + pbrms->seqno, pbrms->reason); } - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - FOR_ALL_INTERFACES (vrf, ifp) { - if (ifp->info) { - pbr_ifp = ifp->info; - if (strcmp(name, pbr_ifp->mapname) == 0) - pbr_map_add_interface(pbrm, ifp); - } - } - } + for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi)) + pbr_send_pbr_map(pbrms, pmi, install); } -void pbr_map_check_policy_change(const char *name) +void pbr_map_install(struct pbr_map *pbrm) { - struct pbr_map *pbrm; + struct listnode *node, *inode; + struct pbr_map_sequence *pbrms; + struct pbr_map_interface *pmi; - pbrm = pbrm_find(name); - if (!pbrm) { - DEBUGD(&pbr_dbg_map, - "%s: Specified PBR-MAP(%s) does not exist?", - __PRETTY_FUNCTION__, name); + if (!pbrm->incoming->count) return; - } - - pbr_map_check_valid(name); - if (pbrm->valid && !pbrm->installed) { - struct pbr_event *pbre; - pbre = pbr_event_new(PBR_MAP_INSTALL, name); + for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) + for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi)) + pbr_send_pbr_map(pbrms, pmi, true); - pbr_event_enqueue(pbre); - } + pbrm->installed = true; } void pbr_map_init(void) diff --git a/pbrd/pbr_map.h b/pbrd/pbr_map.h index fca59951b5..12d49d98c0 100644 --- a/pbrd/pbr_map.h +++ b/pbrd/pbr_map.h @@ -104,7 +104,11 @@ struct pbr_map_sequence { */ bool nhs_installed; + /* + * Are we installed + */ bool installed; + /* * A reason of 0 means we think the pbr_map_sequence is good to go * We can accumuluate multiple failure states @@ -115,7 +119,6 @@ struct pbr_map_sequence { #define PBR_MAP_INVALID_NO_NEXTHOPS (1 << 2) #define PBR_MAP_INVALID_BOTH_NHANDGRP (1 << 3) #define PBR_MAP_INVALID_SRCDST (1 << 4) -#define PBR_MAP_DEL_SEQUENCE_NUMBER (1 << 5) uint64_t reason; QOBJ_FIELDS @@ -130,7 +133,8 @@ extern struct pbr_map_sequence *pbrms_lookup_unique(uint32_t unique, ifindex_t ifindex); extern struct pbr_map *pbrm_find(const char *name); -extern void pbr_map_delete(const char *name, uint32_t seqno); +extern void pbr_map_delete(struct pbr_map_sequence *pbrms); +extern void pbr_map_delete_nexthop_group(struct pbr_map_sequence *pbrms); extern void pbr_map_add_interface(struct pbr_map *pbrm, struct interface *ifp); extern void pbr_map_interface_delete(struct pbr_map *pbrm, struct interface *ifp); @@ -139,16 +143,15 @@ extern void pbr_map_init(void); extern bool pbr_map_check_valid(const char *name); -extern void pbr_map_check(const char *name, uint32_t seqno); +extern void pbr_map_check(struct pbr_map_sequence *pbrms); extern void pbr_map_check_nh_group_change(const char *nh_group); -extern void pbr_map_check_policy_change(const char *name); extern void pbr_map_reason_string(unsigned int reason, char *buf, int size); -extern void pbr_map_add_interfaces(const char *name); extern void pbr_map_schedule_policy_from_nhg(const char *nh_group); -extern void pbr_map_install(const char *name); +extern void pbr_map_install(struct pbr_map *pbrm); extern void pbr_map_policy_install(const char *name); -extern void pbr_map_policy_delete(const char *ifname); +extern void pbr_map_policy_delete(struct pbr_map *pbrm, + struct pbr_map_interface *pmi); #endif diff --git a/pbrd/pbr_nht.c b/pbrd/pbr_nht.c index 63d509bf6b..7586790c85 100644 --- a/pbrd/pbr_nht.c +++ b/pbrd/pbr_nht.c @@ -26,10 +26,10 @@ #include <jhash.h> #include <vty.h> #include <zclient.h> +#include <debug.h> #include "pbrd/pbr_nht.h" #include "pbrd/pbr_map.h" -#include "pbrd/pbr_event.h" #include "pbrd/pbr_zebra.h" #include "pbrd/pbr_memory.h" #include "pbrd/pbr_debug.h" @@ -37,6 +37,7 @@ DEFINE_MTYPE_STATIC(PBRD, PBR_NHG, "PBR Nexthop Groups") static struct hash *pbr_nhg_hash; +static struct hash *pbr_nhrc_hash; static uint32_t pbr_nhg_low_table; static uint32_t pbr_nhg_high_table; @@ -44,18 +45,55 @@ static uint32_t pbr_nhg_low_rule; static uint32_t pbr_nhg_high_rule; static bool nhg_tableid[65535]; +static void pbr_nht_install_nexthop_group(struct pbr_nexthop_group_cache *pnhgc, + struct nexthop_group nhg); + +/* + * Nexthop refcount. + */ +struct nhrc { + struct nexthop nexthop; + unsigned int refcount; +}; + +/* Hash functions for pbr_nhrc_hash ---------------------------------------- */ + +static void *pbr_nhrc_hash_alloc(void *p) +{ + struct nhrc *nhrc = XCALLOC(MTYPE_PBR_NHG, sizeof(struct nhrc)); + nhrc->nexthop = *(struct nexthop *)p; + return nhrc; +} + +static int pbr_nhrc_hash_equal(const void *arg1, const void *arg2) +{ + const struct nexthop *nh1, *nh2; + + nh1 = arg1; + nh2 = arg2; + + return nexthop_same(nh1, nh2); +} + +/* ------------------------------------------------------------------------- */ + static void *pbr_nh_alloc(void *p) { struct pbr_nexthop_cache *new; struct pbr_nexthop_cache *pnhc = (struct pbr_nexthop_cache *)p; + struct nhrc *nhrc; new = XCALLOC(MTYPE_PBR_NHG, sizeof(*new)); - memcpy(&new->nexthop, &pnhc->nexthop, sizeof(struct nexthop)); + nhrc = hash_get(pbr_nhrc_hash, pnhc->nexthop, pbr_nhrc_hash_alloc); + new->nexthop = &nhrc->nexthop; + + /* Decremented again in pbr_nh_delete */ + ++nhrc->refcount; DEBUGD(&pbr_dbg_nht, "%s: Sending nexthop to Zebra", __PRETTY_FUNCTION__); - pbr_send_rnh(&new->nexthop, true); + pbr_send_rnh(new->nexthop, true); new->valid = false; return new; @@ -63,20 +101,36 @@ static void *pbr_nh_alloc(void *p) static void pbr_nh_delete(struct pbr_nexthop_cache **pnhc) { - pbr_send_rnh(&(*pnhc)->nexthop, false); + struct nhrc *nhrc; + + nhrc = hash_lookup(pbr_nhrc_hash, (*pnhc)->nexthop); + + if (nhrc) + --nhrc->refcount; + if (!nhrc || nhrc->refcount == 0) { + DEBUGD(&pbr_dbg_nht, "%s: Removing nexthop from Zebra", + __PRETTY_FUNCTION__); + pbr_send_rnh((*pnhc)->nexthop, false); + } + if (nhrc && nhrc->refcount == 0) { + hash_release(pbr_nhrc_hash, nhrc); + XFREE(MTYPE_PBR_NHG, nhrc); + } XFREE(MTYPE_PBR_NHG, *pnhc); } +static void pbr_nh_delete_iterate(struct hash_backet *b, void *p) +{ + pbr_nh_delete((struct pbr_nexthop_cache **)&b->data); +} + static uint32_t pbr_nh_hash_key(void *arg) { uint32_t key; struct pbr_nexthop_cache *pbrnc = (struct pbr_nexthop_cache *)arg; - key = jhash_1word(pbrnc->nexthop.vrf_id, 0x45afe398); - key = jhash_1word(pbrnc->nexthop.ifindex, key); - key = jhash_1word(pbrnc->nexthop.type, key); - key = jhash(&pbrnc->nexthop.gate, sizeof(union g_addr), key); + key = nexthop_hash(pbrnc->nexthop); return key; } @@ -88,28 +142,28 @@ static int pbr_nh_hash_equal(const void *arg1, const void *arg2) const struct pbr_nexthop_cache *pbrnc2 = (const struct pbr_nexthop_cache *)arg2; - if (pbrnc1->nexthop.vrf_id != pbrnc2->nexthop.vrf_id) + if (pbrnc1->nexthop->vrf_id != pbrnc2->nexthop->vrf_id) return 0; - if (pbrnc1->nexthop.ifindex != pbrnc2->nexthop.ifindex) + if (pbrnc1->nexthop->ifindex != pbrnc2->nexthop->ifindex) return 0; - if (pbrnc1->nexthop.type != pbrnc2->nexthop.type) + if (pbrnc1->nexthop->type != pbrnc2->nexthop->type) return 0; - switch (pbrnc1->nexthop.type) { + switch (pbrnc1->nexthop->type) { case NEXTHOP_TYPE_IFINDEX: return 1; case NEXTHOP_TYPE_IPV4_IFINDEX: case NEXTHOP_TYPE_IPV4: - return pbrnc1->nexthop.gate.ipv4.s_addr - == pbrnc2->nexthop.gate.ipv4.s_addr; + return pbrnc1->nexthop->gate.ipv4.s_addr + == pbrnc2->nexthop->gate.ipv4.s_addr; case NEXTHOP_TYPE_IPV6_IFINDEX: case NEXTHOP_TYPE_IPV6: - return !memcmp(&pbrnc1->nexthop.gate.ipv6, - &pbrnc2->nexthop.gate.ipv6, 16); + return !memcmp(&pbrnc1->nexthop->gate.ipv6, + &pbrnc2->nexthop->gate.ipv6, 16); case NEXTHOP_TYPE_BLACKHOLE: - return pbrnc1->nexthop.bh_type == pbrnc2->nexthop.bh_type; + return pbrnc1->nexthop->bh_type == pbrnc2->nexthop->bh_type; } /* @@ -118,50 +172,118 @@ static int pbr_nh_hash_equal(const void *arg1, const void *arg2) return 0; } +static void pbr_nhgc_delete(struct pbr_nexthop_group_cache *p) +{ + hash_iterate(p->nhh, pbr_nh_delete_iterate, NULL); + hash_free(p->nhh); + XFREE(MTYPE_PBR_NHG, p); +} + +static void *pbr_nhgc_alloc(void *p) +{ + struct pbr_nexthop_group_cache *new; + struct pbr_nexthop_group_cache *pnhgc = + (struct pbr_nexthop_group_cache *)p; + + new = XCALLOC(MTYPE_PBR_NHG, sizeof(*new)); + + strcpy(new->name, pnhgc->name); + new->table_id = pbr_nht_get_next_tableid(); + + DEBUGD(&pbr_dbg_nht, "%s: NHT: %s assigned Table ID: %u", + __PRETTY_FUNCTION__, new->name, new->table_id); + + new->nhh = hash_create_size(8, pbr_nh_hash_key, pbr_nh_hash_equal, + "PBR NH Cache Hash"); + return new; +} + + void pbr_nhgroup_add_cb(const char *name) { - struct pbr_event *pbre; + struct pbr_nexthop_group_cache *pnhgc; + struct nexthop_group_cmd *nhgc; - pbre = pbr_event_new(PBR_NHG_NEW, name); + nhgc = nhgc_find(name); + pnhgc = pbr_nht_add_group(name); - pbr_event_enqueue(pbre); - DEBUGD(&pbr_dbg_nht, "%s: Received ADD cb for %s", __PRETTY_FUNCTION__, + DEBUGD(&pbr_dbg_nht, "%s: Added nexthop-group %s", __PRETTY_FUNCTION__, name); + + pbr_nht_install_nexthop_group(pnhgc, nhgc->nhg); + pbr_map_check_nh_group_change(name); } -void pbr_nhgroup_add_nexthop_cb(const struct nexthop_group_cmd *nhg, +void pbr_nhgroup_add_nexthop_cb(const struct nexthop_group_cmd *nhgc, const struct nexthop *nhop) { - struct pbr_event *pbre; + char debugstr[256]; + struct pbr_nexthop_group_cache pnhgc_find = {}; + struct pbr_nexthop_group_cache *pnhgc; + struct pbr_nexthop_cache pnhc_find = {}; + struct pbr_nexthop_cache *pnhc; + + /* find pnhgc by name */ + strlcpy(pnhgc_find.name, nhgc->name, sizeof(pnhgc_find.name)); + pnhgc = hash_get(pbr_nhg_hash, &pnhgc_find, pbr_nhgc_alloc); - pbre = pbr_event_new(PBR_NHG_ADD_NEXTHOP, nhg->name); + /* create & insert new pnhc into pnhgc->nhh */ + pnhc_find.nexthop = (struct nexthop *)nhop; + pnhc = hash_get(pnhgc->nhh, &pnhc_find, pbr_nh_alloc); + pnhc_find.nexthop = NULL; + + /* set parent pnhgc */ + pnhc->parent = pnhgc; - pbr_event_enqueue(pbre); - DEBUGD(&pbr_dbg_nht, "%s: Received NEXTHOP_ADD cb for %s", - __PRETTY_FUNCTION__, nhg->name); + if (DEBUG_MODE_CHECK(&pbr_dbg_nht, DEBUG_MODE_ALL)) { + nexthop2str(nhop, debugstr, sizeof(debugstr)); + DEBUGD(&pbr_dbg_nht, "%s: Added %s to nexthop-group %s", + __PRETTY_FUNCTION__, debugstr, nhgc->name); + } + + pbr_nht_install_nexthop_group(pnhgc, nhgc->nhg); + pbr_map_check_nh_group_change(nhgc->name); } -void pbr_nhgroup_del_nexthop_cb(const struct nexthop_group_cmd *nhg, +void pbr_nhgroup_del_nexthop_cb(const struct nexthop_group_cmd *nhgc, const struct nexthop *nhop) { - struct pbr_event *pbre; + char debugstr[256]; + struct pbr_nexthop_group_cache pnhgc_find = {}; + struct pbr_nexthop_group_cache *pnhgc; + struct pbr_nexthop_cache pnhc_find = {}; + struct pbr_nexthop_cache *pnhc; + + /* find pnhgc by name */ + strlcpy(pnhgc_find.name, nhgc->name, sizeof(pnhgc_find.name)); + pnhgc = hash_get(pbr_nhg_hash, &pnhgc_find, pbr_nhgc_alloc); + + /* delete pnhc from pnhgc->nhh */ + pnhc_find.nexthop = (struct nexthop *)nhop; + pnhc = hash_release(pnhgc->nhh, &pnhc_find); + + /* delete pnhc */ + pbr_nh_delete(&pnhc); - pbre = pbr_event_new(PBR_NHG_DEL_NEXTHOP, nhg->name); + if (DEBUG_MODE_CHECK(&pbr_dbg_nht, DEBUG_MODE_ALL)) { + nexthop2str(nhop, debugstr, sizeof(debugstr)); + DEBUGD(&pbr_dbg_nht, "%s: Removed %s from nexthop-group %s", + __PRETTY_FUNCTION__, debugstr, nhgc->name); + } - pbr_event_enqueue(pbre); - DEBUGD(&pbr_dbg_nht, "%s: Received NEXTHOP_DEL cb for %s", - __PRETTY_FUNCTION__, nhg->name); + pbr_nht_install_nexthop_group(pnhgc, nhgc->nhg); + pbr_map_check_nh_group_change(nhgc->name); } void pbr_nhgroup_delete_cb(const char *name) { - struct pbr_event *pbre; + /* delete group from all pbrms's */ + pbr_nht_delete_group(name); - pbre = pbr_event_new(PBR_NHG_DELETE, name); - - pbr_event_enqueue(pbre); - DEBUGD(&pbr_dbg_nht, "%s: Received DELETE cb for %s", + DEBUGD(&pbr_dbg_nht, "%s: Removed nexthop-group %s", __PRETTY_FUNCTION__, name); + + pbr_map_check_nh_group_change(name); } #if 0 @@ -307,7 +429,7 @@ void pbr_nht_change_group(const char *name) struct pbr_nexthop_cache lookup; struct pbr_nexthop_cache *pnhc; - memcpy(&lookup.nexthop, nhop, sizeof(*nhop)); + lookup.nexthop = nhop; pnhc = hash_lookup(pnhgc->nhh, &lookup); if (!pnhc) { pnhc = hash_get(pnhgc->nhh, &lookup, pbr_nh_alloc); @@ -324,35 +446,13 @@ char *pbr_nht_nexthop_make_name(char *name, size_t l, return buffer; } -static void *pbr_nhgc_alloc(void *p) -{ - struct pbr_nexthop_group_cache *new; - struct pbr_nexthop_group_cache *pnhgc = - (struct pbr_nexthop_group_cache *)p; - - new = XCALLOC(MTYPE_PBR_NHG, sizeof(*new)); - - strcpy(new->name, pnhgc->name); - new->table_id = pbr_nht_get_next_tableid(); - - DEBUGD(&pbr_dbg_nht, "%s: NHT: %s assigned Table ID: %u", - __PRETTY_FUNCTION__, new->name, new->table_id); - - new->nhh = hash_create_size(8, pbr_nh_hash_key, pbr_nh_hash_equal, - "PBR NH Cache Hash"); - return new; -} - -void pbr_nht_add_individual_nexthop(const char *name, uint32_t seqno) +void pbr_nht_add_individual_nexthop(struct pbr_map_sequence *pbrms) { struct pbr_nexthop_group_cache *pnhgc; struct pbr_nexthop_group_cache find; struct pbr_nexthop_cache *pnhc; - struct pbr_map_sequence *pbrms; struct pbr_nexthop_cache lookup; - pbrms = pbrms_get(name, seqno); - memset(&find, 0, sizeof(find)); pbr_nht_nexthop_make_name(pbrms->parent->name, PBR_MAP_NAMELEN, pbrms->seqno, find.name); @@ -361,29 +461,39 @@ void pbr_nht_add_individual_nexthop(const char *name, uint32_t seqno) pnhgc = hash_get(pbr_nhg_hash, &find, pbr_nhgc_alloc); - memcpy(&lookup.nexthop, pbrms->nhg->nexthop, sizeof(struct nexthop)); + lookup.nexthop = pbrms->nhg->nexthop; pnhc = hash_get(pnhgc->nhh, &lookup, pbr_nh_alloc); pnhc->parent = pnhgc; pbr_nht_install_nexthop_group(pnhgc, *pbrms->nhg); } -void pbr_nht_delete_individual_nexthop(const char *name, uint32_t seqno) +void pbr_nht_delete_individual_nexthop(struct pbr_map_sequence *pbrms) { struct pbr_nexthop_group_cache *pnhgc; struct pbr_nexthop_group_cache find; struct pbr_nexthop_cache *pnhc; struct pbr_nexthop_cache lup; - struct pbr_map_sequence *pbrms; + struct pbr_map *pbrm = pbrms->parent; + struct listnode *node; + struct pbr_map_interface *pmi; struct nexthop *nh; - pbrms = pbrms_get(name, seqno); + if (pbrm->valid && pbrms->nhs_installed && pbrm->incoming->count) { + for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, node, pmi)) + pbr_send_pbr_map(pbrms, pmi, false); + } + + pbrm->valid = false; + pbrms->nhs_installed = false; + pbrms->installed = false; + pbrms->reason |= PBR_MAP_INVALID_NO_NEXTHOPS; memset(&find, 0, sizeof(find)); strcpy(&find.name[0], pbrms->internal_nhg_name); pnhgc = hash_lookup(pbr_nhg_hash, &find); nh = pbrms->nhg->nexthop; - memcpy(&lup.nexthop, nh, sizeof(struct nexthop)); + lup.nexthop = nh; pnhc = hash_lookup(pnhgc->nhh, &lup); pnhc->parent = NULL; hash_release(pnhgc->nhh, pnhc); @@ -398,7 +508,7 @@ void pbr_nht_delete_individual_nexthop(const char *name, uint32_t seqno) XFREE(MTYPE_TMP, pbrms->internal_nhg_name); } -void pbr_nht_add_group(const char *name) +struct pbr_nexthop_group_cache *pbr_nht_add_group(const char *name) { struct nexthop *nhop; struct nexthop_group_cmd *nhgc; @@ -410,7 +520,7 @@ void pbr_nht_add_group(const char *name) if (!nhgc) { zlog_warn("%s: Could not find group %s to add", __PRETTY_FUNCTION__, name); - return; + return NULL; } strcpy(lookup.name, name); @@ -422,13 +532,15 @@ void pbr_nht_add_group(const char *name) struct pbr_nexthop_cache lookup; struct pbr_nexthop_cache *pnhc; - memcpy(&lookup.nexthop, nhop, sizeof(*nhop)); + lookup.nexthop = nhop; pnhc = hash_lookup(pnhgc->nhh, &lookup); if (!pnhc) { pnhc = hash_get(pnhgc->nhh, &lookup, pbr_nh_alloc); pnhc->parent = pnhgc; } } + + return pnhgc; } void pbr_nht_delete_group(const char *name) @@ -436,16 +548,25 @@ void pbr_nht_delete_group(const char *name) struct pbr_map_sequence *pbrms; struct listnode *snode; struct pbr_map *pbrm; + struct pbr_nexthop_group_cache pnhgc_find; + struct pbr_nexthop_group_cache *pnhgc; RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) { for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, snode, pbrms)) { if (pbrms->nhgrp_name - && strcmp(pbrms->nhgrp_name, name) == 0) { + && strmatch(pbrms->nhgrp_name, name)) { pbrms->reason |= PBR_MAP_INVALID_NO_NEXTHOPS; + nexthop_group_delete(&pbrms->nhg); + pbrms->nhg = NULL; + pbrms->internal_nhg_name = NULL; pbrm->valid = false; } } } + + strlcpy(pnhgc_find.name, name, sizeof(pnhgc_find.name)); + pnhgc = hash_release(pbr_nhg_hash, &pnhgc_find); + pbr_nhgc_delete(pnhgc); } bool pbr_nht_nexthop_valid(struct nexthop_group *nhg) @@ -491,13 +612,14 @@ static void pbr_nht_individual_nexthop_update_lookup(struct hash_backet *b, switch (pnhi->nhr->prefix.family) { case AF_INET: - if (pnhc->nexthop.gate.ipv4.s_addr + if (pnhc->nexthop->gate.ipv4.s_addr == pnhi->nhr->prefix.u.prefix4.s_addr) pnhc->valid = !!pnhi->nhr->nexthop_num; break; case AF_INET6: - if (memcmp(&pnhc->nexthop.gate.ipv6, - &pnhi->nhr->prefix.u.prefix6, 16) == 0) + if (memcmp(&pnhc->nexthop->gate.ipv6, + &pnhi->nhr->prefix.u.prefix6, 16) + == 0) pnhc->valid = !!pnhi->nhr->nexthop_num; break; } @@ -506,14 +628,6 @@ static void pbr_nht_individual_nexthop_update_lookup(struct hash_backet *b, prefix2str(&pnhi->nhr->prefix, buf, sizeof(buf)), old_valid, pnhc->valid); - if (old_valid != pnhc->valid) { - struct pbr_event *pbre; - - pbre = pbr_event_new(PBR_NH_CHANGED, pnhc->parent->name); - - pbr_event_enqueue(pbre); - } - if (pnhc->valid) pnhi->valid += 1; } @@ -522,6 +636,9 @@ static void pbr_nht_nexthop_update_lookup(struct hash_backet *b, void *data) { struct pbr_nexthop_group_cache *pnhgc = b->data; struct pbr_nht_individual pnhi; + bool old_valid; + + old_valid = pnhgc->valid; pnhi.nhr = (struct zapi_route *)data; pnhi.valid = 0; @@ -532,6 +649,9 @@ static void pbr_nht_nexthop_update_lookup(struct hash_backet *b, void *data) * If any of the specified nexthops are valid we are valid */ pnhgc->valid = !!pnhi.valid; + + if (old_valid != pnhgc->valid) + pbr_map_check_nh_group_change(pnhgc->name); } void pbr_nht_nexthop_update(struct zapi_route *nhr) @@ -652,7 +772,7 @@ static void pbr_nht_show_nhg_nexthops(struct hash_backet *b, void *data) struct vty *vty = data; vty_out(vty, "\tValid: %d", pnhc->valid); - nexthop_group_write_nexthop(vty, &pnhc->nexthop); + nexthop_group_write_nexthop(vty, pnhc->nexthop); } struct pbr_nht_show { @@ -690,6 +810,9 @@ void pbr_nht_init(void) { pbr_nhg_hash = hash_create_size( 16, pbr_nhg_hash_key, pbr_nhg_hash_equal, "PBR NHG Cache Hash"); + pbr_nhrc_hash = + hash_create_size(16, (unsigned int (*)(void *))nexthop_hash, + pbr_nhrc_hash_equal, "PBR NH Hash"); pbr_nhg_low_table = PBR_NHT_DEFAULT_LOW_TABLEID; pbr_nhg_high_table = PBR_NHT_DEFAULT_HIGH_TABLEID; diff --git a/pbrd/pbr_nht.h b/pbrd/pbr_nht.h index 2508f49e4b..2cfb076f00 100644 --- a/pbrd/pbr_nht.h +++ b/pbrd/pbr_nht.h @@ -23,6 +23,8 @@ #include <lib/zclient.h> #include <lib/nexthop_group.h> +#include "pbr_map.h" + struct pbr_nexthop_group_cache { char name[PBR_MAP_NAMELEN]; @@ -41,7 +43,7 @@ struct pbr_nexthop_group_cache { struct pbr_nexthop_cache { struct pbr_nexthop_group_cache *parent; - struct nexthop nexthop; + struct nexthop *nexthop; bool valid; }; @@ -76,12 +78,12 @@ extern void pbr_nhgroup_delete_cb(const char *name); extern bool pbr_nht_nexthop_valid(struct nexthop_group *nhg); extern bool pbr_nht_nexthop_group_valid(const char *name); -extern void pbr_nht_add_group(const char *name); +extern struct pbr_nexthop_group_cache *pbr_nht_add_group(const char *name); extern void pbr_nht_change_group(const char *name); extern void pbr_nht_delete_group(const char *name); -extern void pbr_nht_add_individual_nexthop(const char *name, uint32_t seqno); -extern void pbr_nht_delete_individual_nexthop(const char *name, uint32_t seqno); +extern void pbr_nht_add_individual_nexthop(struct pbr_map_sequence *pbrms); +extern void pbr_nht_delete_individual_nexthop(struct pbr_map_sequence *pbrms); /* * Given the tableid of the installed default * route, find the nexthop-group associated with diff --git a/pbrd/pbr_vty.c b/pbrd/pbr_vty.c index 6787edbe07..042d940646 100644 --- a/pbrd/pbr_vty.c +++ b/pbrd/pbr_vty.c @@ -33,7 +33,6 @@ #include "pbrd/pbr_map.h" #include "pbrd/pbr_zebra.h" #include "pbrd/pbr_vty.h" -#include "pbrd/pbr_event.h" #include "pbrd/pbr_debug.h" #ifndef VTYSH_EXTRACT_PL #include "pbrd/pbr_vty_clippy.c" @@ -65,7 +64,6 @@ DEFUN_NOSH(no_pbr_map, no_pbr_map_cmd, "no pbr-map WORD [seq (1-65535)]", const char *pbrm_name = argv[2]->arg; uint32_t seqno = 0; struct pbr_map *pbrm = pbrm_find(pbrm_name); - struct pbr_event *pbre; struct pbr_map_sequence *pbrms; struct listnode *node, *next_node; @@ -77,20 +75,12 @@ DEFUN_NOSH(no_pbr_map, no_pbr_map_cmd, "no pbr-map WORD [seq (1-65535)]", return CMD_SUCCESS; } - if (seqno) { - pbrms = pbrms_get(pbrm->name, seqno); - pbrms->reason |= PBR_MAP_DEL_SEQUENCE_NUMBER; - } else { - for (ALL_LIST_ELEMENTS(pbrm->seqnumbers, node, next_node, - pbrms)) { - if (pbrms) - pbrms->reason |= PBR_MAP_DEL_SEQUENCE_NUMBER; - } - } + for (ALL_LIST_ELEMENTS(pbrm->seqnumbers, node, next_node, pbrms)) { + if (seqno && pbrms->seqno != seqno) + continue; - pbre = pbr_event_new(PBR_MAP_DELETE, pbrm_name); - pbre->seqno = seqno; - pbr_event_enqueue(pbre); + pbr_map_delete(pbrms); + } return CMD_SUCCESS; } @@ -104,7 +94,6 @@ DEFPY(pbr_map_match_src, pbr_map_match_src_cmd, "v6 Prefix\n") { struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence); - struct pbr_event *pbre; if (!no) { if (!pbrms->src) @@ -115,9 +104,7 @@ DEFPY(pbr_map_match_src, pbr_map_match_src_cmd, pbrms->src = 0; } - pbre = pbr_event_new(PBR_MAP_MODIFY, pbrms->parent->name); - pbre->seqno = pbrms->seqno; - pbr_event_enqueue(pbre); + pbr_map_check(pbrms); return CMD_SUCCESS; } @@ -131,7 +118,6 @@ DEFPY(pbr_map_match_dst, pbr_map_match_dst_cmd, "v6 Prefix\n") { struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence); - struct pbr_event *pbre; if (!no) { if (!pbrms->dst) @@ -139,12 +125,10 @@ DEFPY(pbr_map_match_dst, pbr_map_match_dst_cmd, prefix_copy(pbrms->dst, prefix); } else { prefix_free(pbrms->dst); - pbrms->dst = 0; + pbrms->dst = NULL; } - pbre = pbr_event_new(PBR_MAP_MODIFY, pbrms->parent->name); - pbre->seqno = pbrms->seqno; - pbr_event_enqueue(pbre); + pbr_map_check(pbrms); return CMD_SUCCESS; } @@ -158,7 +142,6 @@ DEFPY(pbr_map_nexthop_group, pbr_map_nexthop_group_cmd, { struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence); struct nexthop_group_cmd *nhgc; - struct pbr_event *pbre; nhgc = nhgc_find(name); if (!nhgc) { @@ -169,8 +152,7 @@ DEFPY(pbr_map_nexthop_group, pbr_map_nexthop_group_cmd, if (no) { if (pbrms->nhgrp_name && strcmp(name, pbrms->nhgrp_name) == 0) - pbre = pbr_event_new(PBR_MAP_NHG_DELETE, - pbrms->parent->name); + pbr_map_delete_nexthop_group(pbrms); else { vty_out(vty, "Nexthop Group specified: %s does not exist to remove", @@ -188,12 +170,9 @@ DEFPY(pbr_map_nexthop_group, pbr_map_nexthop_group_cmd, return CMD_SUCCESS; } pbrms->nhgrp_name = XSTRDUP(MTYPE_TMP, name); - pbre = pbr_event_new(PBR_MAP_NHG_ADD, pbrms->parent->name); + pbr_map_check(pbrms); } - pbre->seqno = pbrms->seqno; - pbr_event_enqueue(pbre); - return CMD_SUCCESS; } @@ -212,7 +191,6 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd, struct vrf *vrf; struct nexthop nhop; struct nexthop *nh; - struct pbr_event *pbre; if (pbrms->nhgrp_name) { vty_out(vty, @@ -282,14 +260,8 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd, } if (no) { - if (nh) { - // nexthop_del(pbrms->nhg, nh); - // nexthop_free(nh); - pbre = pbr_event_new(PBR_MAP_NEXTHOP_DELETE, - pbrms->parent->name); - pbre->seqno = pbrms->seqno; - pbr_event_enqueue(pbre); - } + if (nh) + pbr_nht_delete_individual_nexthop(pbrms); } else if (!nh) { if (pbrms->nhg->nexthop) { @@ -304,9 +276,8 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd, memcpy(nh, &nhop, sizeof(nhop)); nexthop_add(&pbrms->nhg->nexthop, nh); - pbre = pbr_event_new(PBR_MAP_NEXTHOP_ADD, pbrms->parent->name); - pbre->seqno = pbrms->seqno; - pbr_event_enqueue(pbre); + pbr_nht_add_individual_nexthop(pbrms); + pbr_map_check(pbrms); } return CMD_SUCCESS; @@ -363,6 +334,14 @@ DEFPY (pbr_policy, pbrm = pbrm_find(mapname); + if (!pbr_ifp) { + /* + * Some one could have fat fingered the interface + * name + */ + pbr_ifp = pbr_if_new(ifp); + } + if (no) { if (strcmp(pbr_ifp->mapname, mapname) == 0) { strcpy(pbr_ifp->mapname, ""); diff --git a/pbrd/pbr_zebra.c b/pbrd/pbr_zebra.c index b066965249..971fe65aaf 100644 --- a/pbrd/pbr_zebra.c +++ b/pbrd/pbr_zebra.c @@ -56,7 +56,7 @@ static struct interface *zebra_interface_if_lookup(struct stream *s) return if_lookup_by_name(ifname_tmp, VRF_DEFAULT); } -static struct pbr_interface *pbr_if_new(struct interface *ifp) +struct pbr_interface *pbr_if_new(struct interface *ifp) { struct pbr_interface *pbr_ifp; @@ -497,14 +497,11 @@ static void pbr_encode_pbr_map_sequence(struct stream *s, stream_putl(s, ifp->ifindex); } -void pbr_send_pbr_map(struct pbr_map *pbrm, bool install) +void pbr_send_pbr_map(struct pbr_map_sequence *pbrms, + struct pbr_map_interface *pmi, bool install) { - struct listnode *inode, *snode; - struct pbr_map_sequence *pbrms; - struct pbr_map_interface *pmi; + struct pbr_map *pbrm = pbrms->parent; struct stream *s; - uint32_t total; - ssize_t tspot; DEBUGD(&pbr_dbg_zebra, "%s: for %s %d", __PRETTY_FUNCTION__, pbrm->name, install); @@ -516,59 +513,18 @@ void pbr_send_pbr_map(struct pbr_map *pbrm, bool install) install ? ZEBRA_RULE_ADD : ZEBRA_RULE_DELETE, VRF_DEFAULT); - total = 0; - tspot = stream_get_endp(s); - stream_putl(s, 0); - for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi)) { - - DEBUGD(&pbr_dbg_zebra, "%s: \t%s %s %d %s %u", - __PRETTY_FUNCTION__, install ? "Installing" : "Deleting", - pbrm->name, install, pmi->ifp->name, pmi->delete); - - if (!install && pmi->delete) { - for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, snode, - pbrms)) { - pbr_encode_pbr_map_sequence(s, - pbrms, pmi->ifp); - total++; - } - continue; - } - - for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, snode, pbrms)) { - - DEBUGD(&pbr_dbg_zebra, "%s: \tSeqno: %u %" PRIu64 " valid %u", - __PRETTY_FUNCTION__, pbrms->seqno, pbrms->reason, - pbrm->valid); - - if (!install && - !(pbrms->reason & PBR_MAP_DEL_SEQUENCE_NUMBER)) - continue; - - if (!install && !pbrms->installed) - continue; - - if (install && pbrms->installed) - continue; + /* + * We are sending one item at a time at the moment + */ + stream_putl(s, 1); - DEBUGD(&pbr_dbg_zebra, "%s: \t Seq: %u ifp %s", - __PRETTY_FUNCTION__, pbrms->seqno, - pmi->ifp->name); + DEBUGD(&pbr_dbg_zebra, "%s: \t%s %s %d %s %u", + __PRETTY_FUNCTION__, install ? "Installing" : "Deleting", + pbrm->name, install, pmi->ifp->name, pmi->delete); - pbr_encode_pbr_map_sequence(s, pbrms, pmi->ifp); - total++; - } - } + pbr_encode_pbr_map_sequence(s, pbrms, pmi->ifp); - DEBUGD(&pbr_dbg_zebra, "%s: Putting %u at %zu ", __PRETTY_FUNCTION__, - total, tspot); - - stream_putl_at(s, tspot, total); stream_putw_at(s, 0, stream_get_endp(s)); - if (!total) { - stream_reset(s); - return; - } zclient_send_message(zclient); } diff --git a/pbrd/pbr_zebra.h b/pbrd/pbr_zebra.h index 6c1eca9d19..4cbefe2636 100644 --- a/pbrd/pbr_zebra.h +++ b/pbrd/pbr_zebra.h @@ -35,5 +35,8 @@ extern void route_delete(struct pbr_nexthop_group_cache *pnhgc, extern void pbr_send_rnh(struct nexthop *nhop, bool reg); -extern void pbr_send_pbr_map(struct pbr_map *pbrm, bool install); +extern void pbr_send_pbr_map(struct pbr_map_sequence *pbrms, + struct pbr_map_interface *pmi, bool install); + +extern struct pbr_interface *pbr_if_new(struct interface *ifp); #endif diff --git a/pbrd/subdir.am b/pbrd/subdir.am index 361e6c1fde..42ab393218 100644 --- a/pbrd/subdir.am +++ b/pbrd/subdir.am @@ -14,12 +14,10 @@ pbrd_libpbr_a_SOURCES = \ pbrd/pbr_map.c \ pbrd/pbr_memory.c \ pbrd/pbr_nht.c \ - pbrd/pbr_event.c \ pbrd/pbr_debug.c \ # end noinst_HEADERS += \ - pbrd/pbr_event.h \ pbrd/pbr_map.h \ pbrd/pbr_memory.h \ pbrd/pbr_nht.h \ |
