summaryrefslogtreecommitdiffstats
path: root/pbrd
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2018-03-19 14:04:17 +0100
committerDonald Sharp <sharpd@cumulusnetworks.com>2018-04-06 19:22:43 +0200
commitb13e5ad68a740b66c921c5ab1314e0898f0ed310 (patch)
treef08e165c4507040ecfd17ec9c10b109f5b5fa941 /pbrd
parentlib: Add hash and use const a bit more intelligently (diff)
downloadfrr-b13e5ad68a740b66c921c5ab1314e0898f0ed310.tar.xz
frr-b13e5ad68a740b66c921c5ab1314e0898f0ed310.zip
pbrd: Remove pbr_events
The pbr_events.c file was a mistake in that it overly complicated the code and made it hard to think about what was happening. Remove all the events and just do the work where needed. Additionally rethink the sending of the pbr map to zebra and only send one notification at a time instead of having the sending function attempt to figure out what to do. Clean up some of the no form of commands to make them work properly. Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com> Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com> Signed-off-by: Don Slice <dslice@cumulusnetworks.com>
Diffstat (limited to 'pbrd')
-rw-r--r--pbrd/pbr_event.c220
-rw-r--r--pbrd/pbr_event.h137
-rw-r--r--pbrd/pbr_main.c3
-rw-r--r--pbrd/pbr_map.c301
-rw-r--r--pbrd/pbr_map.h17
-rw-r--r--pbrd/pbr_nht.c289
-rw-r--r--pbrd/pbr_nht.h10
-rw-r--r--pbrd/pbr_vty.c65
-rw-r--r--pbrd/pbr_zebra.c68
-rw-r--r--pbrd/pbr_zebra.h5
-rw-r--r--pbrd/subdir.am2
11 files changed, 378 insertions, 739 deletions
diff --git a/pbrd/pbr_event.c b/pbrd/pbr_event.c
deleted file mode 100644
index 4563d7d91..000000000
--- 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 2d895d969..000000000
--- 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 83cac6daa..638e284a1 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 3b058675d..8e4d52cbc 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 fca59951b..12d49d98c 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 63d509bf6..7586790c8 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 2508f49e4..2cfb076f0 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 6787edbe0..042d94064 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 b06696524..971fe65aa 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 6c1eca9d1..4cbefe263 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 361e6c1fd..42ab39321 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 \