summaryrefslogtreecommitdiff
path: root/pbrd
diff options
context:
space:
mode:
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 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 \