mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-30 02:22:45 +00:00
pbrd: Add set vrf NAME
and set vrf unchanged
`set vrf NAME` allows the pbr map to point to an arbitrary vrf table. `set vrf unchanged` will use the interface's vrf for table lookup. Further, add functionality for pbr to respond to interface events such as interface vrf changes & interface creation/deletion. Ex) ubuntu_nh# show pbr map pbr-map TEST valid: 1 Seq: 1 rule: 300 Installed: 3(1) Reason: Valid SRC Match: 3.3.3.3/32 VRF Unchanged (use interface vrf) pbr-map TEST2 valid: 1 Seq: 2 rule: 301 Installed: 3(2) Reason: Valid SRC Match: 4.4.4.4/32 VRF Lookup: vrf-red root@ubuntu_nh:/home# ip rule show 0: from all lookup local 300: from 3.3.3.3 iif dummy2 lookup main 300: from 3.3.3.3 iif dummyVRF lookup 1111 301: from 4.4.4.4 iif dummy1 lookup 1111 301: from 4.4.4.4 iif dummy3 lookup 1111 Signed-off-by: Stephen Worley <sworley@cumulusnetworks.com-
This commit is contained in:
parent
2d7ef3bba7
commit
be3b67b5ef
@ -107,6 +107,14 @@ end destination.
|
|||||||
Use this individual nexthop as the place to forward packets when the match
|
Use this individual nexthop as the place to forward packets when the match
|
||||||
commands have matched a packet.
|
commands have matched a packet.
|
||||||
|
|
||||||
|
.. clicmd:: set vrf unchanged|NAME
|
||||||
|
|
||||||
|
If unchanged is set, the rule will use the vrf table the interface is in
|
||||||
|
as its lookup. If NAME is specified, the rule will use that vrf table as
|
||||||
|
its lookup.
|
||||||
|
|
||||||
|
Not supported with NETNS VRF backend.
|
||||||
|
|
||||||
.. _pbr-policy:
|
.. _pbr-policy:
|
||||||
|
|
||||||
PBR Policy
|
PBR Policy
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
#include "pbr_zebra.h"
|
#include "pbr_zebra.h"
|
||||||
#include "pbr_vty.h"
|
#include "pbr_vty.h"
|
||||||
#include "pbr_debug.h"
|
#include "pbr_debug.h"
|
||||||
|
#include "pbr_vrf.h"
|
||||||
|
|
||||||
zebra_capabilities_t _caps_p[] = {
|
zebra_capabilities_t _caps_p[] = {
|
||||||
ZCAP_NET_RAW, ZCAP_BIND, ZCAP_NET_ADMIN,
|
ZCAP_NET_RAW, ZCAP_BIND, ZCAP_NET_ADMIN,
|
||||||
@ -153,7 +154,6 @@ int main(int argc, char **argv, char **envp)
|
|||||||
|
|
||||||
pbr_debug_init();
|
pbr_debug_init();
|
||||||
|
|
||||||
vrf_init(NULL, NULL, NULL, NULL, NULL);
|
|
||||||
nexthop_group_init(pbr_nhgroup_add_cb,
|
nexthop_group_init(pbr_nhgroup_add_cb,
|
||||||
pbr_nhgroup_add_nexthop_cb,
|
pbr_nhgroup_add_nexthop_cb,
|
||||||
pbr_nhgroup_del_nexthop_cb,
|
pbr_nhgroup_del_nexthop_cb,
|
||||||
@ -169,6 +169,7 @@ int main(int argc, char **argv, char **envp)
|
|||||||
if_zapi_callbacks(pbr_ifp_create, pbr_ifp_up,
|
if_zapi_callbacks(pbr_ifp_create, pbr_ifp_up,
|
||||||
pbr_ifp_down, pbr_ifp_destroy);
|
pbr_ifp_down, pbr_ifp_destroy);
|
||||||
pbr_zebra_init();
|
pbr_zebra_init();
|
||||||
|
pbr_vrf_init();
|
||||||
pbr_vty_init();
|
pbr_vty_init();
|
||||||
|
|
||||||
frr_config_fork();
|
frr_config_fork();
|
||||||
|
210
pbrd/pbr_map.c
210
pbrd/pbr_map.c
@ -35,6 +35,7 @@
|
|||||||
#include "pbr_zebra.h"
|
#include "pbr_zebra.h"
|
||||||
#include "pbr_memory.h"
|
#include "pbr_memory.h"
|
||||||
#include "pbr_debug.h"
|
#include "pbr_debug.h"
|
||||||
|
#include "pbr_vrf.h"
|
||||||
|
|
||||||
DEFINE_MTYPE_STATIC(PBRD, PBR_MAP, "PBR Map")
|
DEFINE_MTYPE_STATIC(PBRD, PBR_MAP, "PBR Map")
|
||||||
DEFINE_MTYPE_STATIC(PBRD, PBR_MAP_SEQNO, "PBR Map Sequence")
|
DEFINE_MTYPE_STATIC(PBRD, PBR_MAP_SEQNO, "PBR Map Sequence")
|
||||||
@ -42,6 +43,7 @@ DEFINE_MTYPE_STATIC(PBRD, PBR_MAP_INTERFACE, "PBR Map Interface")
|
|||||||
|
|
||||||
static uint32_t pbr_map_sequence_unique;
|
static uint32_t pbr_map_sequence_unique;
|
||||||
|
|
||||||
|
static bool pbr_map_check_valid_internal(struct pbr_map *pbrm);
|
||||||
static inline int pbr_map_compare(const struct pbr_map *pbrmap1,
|
static inline int pbr_map_compare(const struct pbr_map *pbrmap1,
|
||||||
const struct pbr_map *pbrmap2);
|
const struct pbr_map *pbrmap2);
|
||||||
|
|
||||||
@ -98,9 +100,55 @@ static void pbr_map_interface_list_delete(struct pbr_map_interface *pmi)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool pbr_map_interface_is_valid(const struct pbr_map_interface *pmi)
|
||||||
|
{
|
||||||
|
/* Don't install rules without a real ifindex on the incoming interface.
|
||||||
|
*
|
||||||
|
* This can happen when we have config for an interface that does not
|
||||||
|
* exist or when an interface is changing vrfs.
|
||||||
|
*/
|
||||||
|
if (pmi->ifp && pmi->ifp->ifindex != IFINDEX_INTERNAL)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pbr_map_pbrms_update_common(struct pbr_map_sequence *pbrms,
|
||||||
|
bool install)
|
||||||
|
{
|
||||||
|
struct pbr_map *pbrm;
|
||||||
|
struct listnode *node;
|
||||||
|
struct pbr_map_interface *pmi;
|
||||||
|
|
||||||
|
pbrm = pbrms->parent;
|
||||||
|
|
||||||
|
if (pbrms->nhs_installed && pbrm->incoming->count) {
|
||||||
|
for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, node, pmi)) {
|
||||||
|
if (!pmi->ifp)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (install && !pbr_map_interface_is_valid(pmi))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
pbr_send_pbr_map(pbrms, pmi, install);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pbr_map_pbrms_install(struct pbr_map_sequence *pbrms)
|
||||||
|
{
|
||||||
|
pbr_map_pbrms_update_common(pbrms, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pbr_map_pbrms_uninstall(struct pbr_map_sequence *pbrms)
|
||||||
|
{
|
||||||
|
pbr_map_pbrms_update_common(pbrms, false);
|
||||||
|
}
|
||||||
|
|
||||||
static const char *pbr_map_reason_str[] = {
|
static const char *pbr_map_reason_str[] = {
|
||||||
"Invalid NH-group", "Invalid NH", "No Nexthops",
|
"Invalid NH-group", "Invalid NH", "No Nexthops",
|
||||||
"Both NH and NH-Group", "Invalid Src or Dst", "Deleting Sequence",
|
"Both NH and NH-Group", "Invalid Src or Dst", "Invalid VRF",
|
||||||
|
"Deleting Sequence",
|
||||||
};
|
};
|
||||||
|
|
||||||
void pbr_map_reason_string(unsigned int reason, char *buf, int size)
|
void pbr_map_reason_string(unsigned int reason, char *buf, int size)
|
||||||
@ -168,6 +216,93 @@ void pbr_map_add_interface(struct pbr_map *pbrm, struct interface *ifp_add)
|
|||||||
pbr_map_install(pbrm);
|
pbr_map_install(pbrm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pbr_map_policy_interface_update_common(const struct interface *ifp,
|
||||||
|
struct pbr_interface **pbr_ifp,
|
||||||
|
struct pbr_map **pbrm)
|
||||||
|
{
|
||||||
|
if (!ifp->info) {
|
||||||
|
DEBUGD(&pbr_dbg_map, "%s: %s has no pbr_interface info",
|
||||||
|
__func__, ifp->name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pbr_ifp = ifp->info;
|
||||||
|
|
||||||
|
*pbrm = pbrm_find((*pbr_ifp)->mapname);
|
||||||
|
|
||||||
|
if (!*pbrm) {
|
||||||
|
DEBUGD(&pbr_dbg_map, "%s: applied PBR-MAP(%s) does not exist?",
|
||||||
|
__func__, (*pbr_ifp)->mapname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pbr_map_policy_interface_update(const struct interface *ifp, bool state_up)
|
||||||
|
{
|
||||||
|
struct pbr_interface *pbr_ifp;
|
||||||
|
struct pbr_map_sequence *pbrms;
|
||||||
|
struct pbr_map *pbrm;
|
||||||
|
struct listnode *node, *inode;
|
||||||
|
struct pbr_map_interface *pmi;
|
||||||
|
|
||||||
|
if (pbr_map_policy_interface_update_common(ifp, &pbr_ifp, &pbrm))
|
||||||
|
return;
|
||||||
|
|
||||||
|
DEBUGD(&pbr_dbg_map, "%s: %s %s rules on interface %s", __func__,
|
||||||
|
pbr_ifp->mapname, (state_up ? "installing" : "removing"),
|
||||||
|
ifp->name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Walk the list and install/remove maps on the interface.
|
||||||
|
*/
|
||||||
|
for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms))
|
||||||
|
for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi))
|
||||||
|
if (pmi->ifp == ifp && pbr_map_interface_is_valid(pmi))
|
||||||
|
pbr_send_pbr_map(pbrms, pmi, state_up);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pbrms_vrf_update(struct pbr_map_sequence *pbrms,
|
||||||
|
const struct pbr_vrf *pbr_vrf)
|
||||||
|
{
|
||||||
|
const char *vrf_name = pbr_vrf_name(pbr_vrf);
|
||||||
|
|
||||||
|
if (pbrms->vrf_lookup
|
||||||
|
&& (strncmp(vrf_name, pbrms->vrf_name, sizeof(pbrms->vrf_name))
|
||||||
|
== 0)) {
|
||||||
|
DEBUGD(&pbr_dbg_map, "\tSeq %u uses vrf %s (%u), updating map",
|
||||||
|
pbrms->seqno, vrf_name, pbr_vrf_id(pbr_vrf));
|
||||||
|
|
||||||
|
pbr_map_check(pbrms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Vrf enabled/disabled */
|
||||||
|
void pbr_map_vrf_update(const struct pbr_vrf *pbr_vrf)
|
||||||
|
{
|
||||||
|
struct pbr_map *pbrm;
|
||||||
|
struct pbr_map_sequence *pbrms;
|
||||||
|
struct listnode *node;
|
||||||
|
|
||||||
|
if (!pbr_vrf)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool enabled = pbr_vrf_is_enabled(pbr_vrf);
|
||||||
|
|
||||||
|
DEBUGD(&pbr_dbg_map, "%s: %s (%u) %s, updating pbr maps", __func__,
|
||||||
|
pbr_vrf_name(pbr_vrf), pbr_vrf_id(pbr_vrf),
|
||||||
|
enabled ? "enabled" : "disabled");
|
||||||
|
|
||||||
|
RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) {
|
||||||
|
DEBUGD(&pbr_dbg_map, "%s: Looking at %s", __PRETTY_FUNCTION__,
|
||||||
|
pbrm->name);
|
||||||
|
for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms))
|
||||||
|
pbrms_vrf_update(pbrms, pbr_vrf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void pbr_map_write_interfaces(struct vty *vty, struct interface *ifp)
|
void pbr_map_write_interfaces(struct vty *vty, struct interface *ifp)
|
||||||
{
|
{
|
||||||
struct pbr_interface *pbr_ifp = ifp->info;
|
struct pbr_interface *pbr_ifp = ifp->info;
|
||||||
@ -210,16 +345,11 @@ extern void pbr_map_delete(struct pbr_map_sequence *pbrms)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pbr_map_delete_nexthop_group(struct pbr_map_sequence *pbrms)
|
static void pbr_map_delete_common(struct pbr_map_sequence *pbrms)
|
||||||
{
|
{
|
||||||
struct pbr_map *pbrm = pbrms->parent;
|
struct pbr_map *pbrm = pbrms->parent;
|
||||||
struct listnode *node;
|
|
||||||
struct pbr_map_interface *pmi;
|
|
||||||
|
|
||||||
if (pbrm->valid && pbrms->nhs_installed && pbrm->incoming->count) {
|
pbr_map_pbrms_uninstall(pbrms);
|
||||||
for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, node, pmi))
|
|
||||||
pbr_send_pbr_map(pbrms, pmi, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
pbrm->valid = false;
|
pbrm->valid = false;
|
||||||
pbrms->nhs_installed = false;
|
pbrms->nhs_installed = false;
|
||||||
@ -227,6 +357,16 @@ void pbr_map_delete_nexthop_group(struct pbr_map_sequence *pbrms)
|
|||||||
pbrms->nhgrp_name = NULL;
|
pbrms->nhgrp_name = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pbr_map_delete_nexthops(struct pbr_map_sequence *pbrms)
|
||||||
|
{
|
||||||
|
pbr_map_delete_common(pbrms);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pbr_map_delete_vrf(struct pbr_map_sequence *pbrms)
|
||||||
|
{
|
||||||
|
pbr_map_delete_common(pbrms);
|
||||||
|
}
|
||||||
|
|
||||||
struct pbr_map_sequence *pbrms_lookup_unique(uint32_t unique, ifindex_t ifindex,
|
struct pbr_map_sequence *pbrms_lookup_unique(uint32_t unique, ifindex_t ifindex,
|
||||||
struct pbr_map_interface **ppmi)
|
struct pbr_map_interface **ppmi)
|
||||||
{
|
{
|
||||||
@ -318,6 +458,7 @@ struct pbr_map_sequence *pbrms_get(const char *name, uint32_t seqno)
|
|||||||
pbrms->reason =
|
pbrms->reason =
|
||||||
PBR_MAP_INVALID_EMPTY |
|
PBR_MAP_INVALID_EMPTY |
|
||||||
PBR_MAP_INVALID_NO_NEXTHOPS;
|
PBR_MAP_INVALID_NO_NEXTHOPS;
|
||||||
|
pbrms->vrf_name[0] = '\0';
|
||||||
|
|
||||||
QOBJ_REG(pbrms, pbr_map_sequence);
|
QOBJ_REG(pbrms, pbr_map_sequence);
|
||||||
listnode_add_sort(pbrm->seqnumbers, pbrms);
|
listnode_add_sort(pbrm->seqnumbers, pbrms);
|
||||||
@ -329,12 +470,36 @@ struct pbr_map_sequence *pbrms_get(const char *name, uint32_t seqno)
|
|||||||
static void
|
static void
|
||||||
pbr_map_sequence_check_nexthops_valid(struct pbr_map_sequence *pbrms)
|
pbr_map_sequence_check_nexthops_valid(struct pbr_map_sequence *pbrms)
|
||||||
{
|
{
|
||||||
|
/* Check if any are present first */
|
||||||
|
if (!pbrms->vrf_unchanged && !pbrms->vrf_lookup && !pbrms->nhg
|
||||||
|
&& !pbrms->nhgrp_name) {
|
||||||
|
pbrms->reason |= PBR_MAP_INVALID_NO_NEXTHOPS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check validness of vrf.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This one can be considered always valid */
|
||||||
|
if (pbrms->vrf_unchanged)
|
||||||
|
pbrms->nhs_installed = true;
|
||||||
|
|
||||||
|
if (pbrms->vrf_lookup) {
|
||||||
|
struct pbr_vrf *pbr_vrf =
|
||||||
|
pbr_vrf_lookup_by_name(pbrms->vrf_name);
|
||||||
|
|
||||||
|
if (pbr_vrf && pbr_vrf_is_valid(pbr_vrf))
|
||||||
|
pbrms->nhs_installed = true;
|
||||||
|
else
|
||||||
|
pbrms->reason |= PBR_MAP_INVALID_VRF;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check validness of the nexthop or nexthop-group
|
* Check validness of the nexthop or nexthop-group
|
||||||
*/
|
*/
|
||||||
if (!pbrms->nhg && !pbrms->nhgrp_name)
|
|
||||||
pbrms->reason |= PBR_MAP_INVALID_NO_NEXTHOPS;
|
|
||||||
|
|
||||||
|
/* Only nexthop or nexthop group allowed */
|
||||||
if (pbrms->nhg && pbrms->nhgrp_name)
|
if (pbrms->nhg && pbrms->nhgrp_name)
|
||||||
pbrms->reason |= PBR_MAP_INVALID_BOTH_NHANDGRP;
|
pbrms->reason |= PBR_MAP_INVALID_BOTH_NHANDGRP;
|
||||||
|
|
||||||
@ -458,11 +623,13 @@ void pbr_map_policy_install(const char *name)
|
|||||||
__PRETTY_FUNCTION__, name, pbrms->seqno, pbrm->valid,
|
__PRETTY_FUNCTION__, name, pbrms->seqno, pbrm->valid,
|
||||||
pbrms->nhs_installed);
|
pbrms->nhs_installed);
|
||||||
|
|
||||||
if (pbrm->valid && pbrms->nhs_installed && pbrm->incoming->count) {
|
if (pbrm->valid && pbrms->nhs_installed
|
||||||
DEBUGD(&pbr_dbg_map, "\tInstalling %s %u",
|
&& pbrm->incoming->count) {
|
||||||
pbrm->name, pbrms->seqno);
|
DEBUGD(&pbr_dbg_map, "\tInstalling %s %u", pbrm->name,
|
||||||
|
pbrms->seqno);
|
||||||
for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi))
|
for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi))
|
||||||
pbr_send_pbr_map(pbrms, pmi, true);
|
if (pbr_map_interface_is_valid(pmi))
|
||||||
|
pbr_send_pbr_map(pbrms, pmi, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -525,8 +692,6 @@ void pbr_map_check_nh_group_change(const char *nh_group)
|
|||||||
void pbr_map_check(struct pbr_map_sequence *pbrms)
|
void pbr_map_check(struct pbr_map_sequence *pbrms)
|
||||||
{
|
{
|
||||||
struct pbr_map *pbrm;
|
struct pbr_map *pbrm;
|
||||||
struct listnode *inode;
|
|
||||||
struct pbr_map_interface *pmi;
|
|
||||||
bool install;
|
bool install;
|
||||||
|
|
||||||
pbrm = pbrms->parent;
|
pbrm = pbrms->parent;
|
||||||
@ -551,23 +716,22 @@ void pbr_map_check(struct pbr_map_sequence *pbrms)
|
|||||||
pbrms->seqno, pbrms->reason);
|
pbrms->seqno, pbrms->reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi)) {
|
if (install)
|
||||||
pbr_send_pbr_map(pbrms, pmi, install);
|
pbr_map_pbrms_install(pbrms);
|
||||||
}
|
else
|
||||||
|
pbr_map_pbrms_uninstall(pbrms);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pbr_map_install(struct pbr_map *pbrm)
|
void pbr_map_install(struct pbr_map *pbrm)
|
||||||
{
|
{
|
||||||
struct listnode *node, *inode;
|
|
||||||
struct pbr_map_sequence *pbrms;
|
struct pbr_map_sequence *pbrms;
|
||||||
struct pbr_map_interface *pmi;
|
struct listnode *node;
|
||||||
|
|
||||||
if (!pbrm->incoming->count)
|
if (!pbrm->incoming->count)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms))
|
for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms))
|
||||||
for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi))
|
pbr_map_pbrms_install(pbrms);
|
||||||
pbr_send_pbr_map(pbrms, pmi, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pbr_map_init(void)
|
void pbr_map_init(void)
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
#include <bitfield.h>
|
#include <bitfield.h>
|
||||||
|
|
||||||
|
#include "pbr_vrf.h"
|
||||||
|
|
||||||
struct pbr_map {
|
struct pbr_map {
|
||||||
/*
|
/*
|
||||||
* RB Tree of the pbr_maps
|
* RB Tree of the pbr_maps
|
||||||
@ -94,6 +96,21 @@ struct pbr_map_sequence {
|
|||||||
*/
|
*/
|
||||||
unsigned char family;
|
unsigned char family;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use interface's vrf.
|
||||||
|
*/
|
||||||
|
bool vrf_unchanged;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The vrf to lookup in was directly configured.
|
||||||
|
*/
|
||||||
|
bool vrf_lookup;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VRF to lookup.
|
||||||
|
*/
|
||||||
|
char vrf_name[VRF_NAMSIZ + 1];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The nexthop group we auto create
|
* The nexthop group we auto create
|
||||||
* for when the user specifies a individual
|
* for when the user specifies a individual
|
||||||
@ -122,12 +139,13 @@ struct pbr_map_sequence {
|
|||||||
* A reason of 0 means we think the pbr_map_sequence is good to go
|
* A reason of 0 means we think the pbr_map_sequence is good to go
|
||||||
* We can accumuluate multiple failure states
|
* We can accumuluate multiple failure states
|
||||||
*/
|
*/
|
||||||
#define PBR_MAP_VALID_SEQUENCE_NUMBER 0
|
#define PBR_MAP_VALID_SEQUENCE_NUMBER 0
|
||||||
#define PBR_MAP_INVALID_NEXTHOP_GROUP (1 << 0)
|
#define PBR_MAP_INVALID_NEXTHOP_GROUP (1 << 0)
|
||||||
#define PBR_MAP_INVALID_NEXTHOP (1 << 1)
|
#define PBR_MAP_INVALID_NEXTHOP (1 << 1)
|
||||||
#define PBR_MAP_INVALID_NO_NEXTHOPS (1 << 2)
|
#define PBR_MAP_INVALID_NO_NEXTHOPS (1 << 2)
|
||||||
#define PBR_MAP_INVALID_BOTH_NHANDGRP (1 << 3)
|
#define PBR_MAP_INVALID_BOTH_NHANDGRP (1 << 3)
|
||||||
#define PBR_MAP_INVALID_EMPTY (1 << 4)
|
#define PBR_MAP_INVALID_EMPTY (1 << 4)
|
||||||
|
#define PBR_MAP_INVALID_VRF (1 << 5)
|
||||||
uint64_t reason;
|
uint64_t reason;
|
||||||
|
|
||||||
QOBJ_FIELDS
|
QOBJ_FIELDS
|
||||||
@ -144,12 +162,21 @@ pbrms_lookup_unique(uint32_t unique, ifindex_t ifindex,
|
|||||||
|
|
||||||
extern struct pbr_map *pbrm_find(const char *name);
|
extern struct pbr_map *pbrm_find(const char *name);
|
||||||
extern void pbr_map_delete(struct pbr_map_sequence *pbrms);
|
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_delete_nexthops(struct pbr_map_sequence *pbrms);
|
||||||
|
extern void pbr_map_delete_vrf(struct pbr_map_sequence *pbrms);
|
||||||
extern void pbr_map_add_interface(struct pbr_map *pbrm, struct interface *ifp);
|
extern void pbr_map_add_interface(struct pbr_map *pbrm, struct interface *ifp);
|
||||||
extern void pbr_map_interface_delete(struct pbr_map *pbrm,
|
extern void pbr_map_interface_delete(struct pbr_map *pbrm,
|
||||||
struct interface *ifp);
|
struct interface *ifp);
|
||||||
|
|
||||||
|
/* Update maps installed on interface */
|
||||||
|
extern void pbr_map_policy_interface_update(const struct interface *ifp,
|
||||||
|
bool state_up);
|
||||||
|
|
||||||
extern void pbr_map_final_interface_deletion(struct pbr_map *pbrm,
|
extern void pbr_map_final_interface_deletion(struct pbr_map *pbrm,
|
||||||
struct pbr_map_interface *pmi);
|
struct pbr_map_interface *pmi);
|
||||||
|
|
||||||
|
extern void pbr_map_vrf_update(const struct pbr_vrf *pbr_vrf);
|
||||||
|
|
||||||
extern void pbr_map_write_interfaces(struct vty *vty, struct interface *ifp);
|
extern void pbr_map_write_interfaces(struct vty *vty, struct interface *ifp);
|
||||||
extern void pbr_map_init(void);
|
extern void pbr_map_init(void);
|
||||||
|
|
||||||
|
@ -548,20 +548,10 @@ void pbr_nht_delete_individual_nexthop(struct pbr_map_sequence *pbrms)
|
|||||||
struct pbr_nexthop_group_cache find;
|
struct pbr_nexthop_group_cache find;
|
||||||
struct pbr_nexthop_cache *pnhc;
|
struct pbr_nexthop_cache *pnhc;
|
||||||
struct pbr_nexthop_cache lup;
|
struct pbr_nexthop_cache lup;
|
||||||
struct pbr_map *pbrm = pbrms->parent;
|
|
||||||
struct listnode *node;
|
|
||||||
struct pbr_map_interface *pmi;
|
|
||||||
struct nexthop *nh;
|
struct nexthop *nh;
|
||||||
enum nexthop_types_t nh_type = 0;
|
enum nexthop_types_t nh_type = 0;
|
||||||
|
|
||||||
if (pbrm->valid && pbrms->nhs_installed && pbrm->incoming->count) {
|
pbr_map_delete_nexthops(pbrms);
|
||||||
for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, node, pmi))
|
|
||||||
pbr_send_pbr_map(pbrms, pmi, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
pbrm->valid = false;
|
|
||||||
pbrms->nhs_installed = false;
|
|
||||||
pbrms->reason |= PBR_MAP_INVALID_NO_NEXTHOPS;
|
|
||||||
|
|
||||||
memset(&find, 0, sizeof(find));
|
memset(&find, 0, sizeof(find));
|
||||||
snprintf(find.name, sizeof(find.name), "%s", pbrms->internal_nhg_name);
|
snprintf(find.name, sizeof(find.name), "%s", pbrms->internal_nhg_name);
|
||||||
|
137
pbrd/pbr_vrf.c
Normal file
137
pbrd/pbr_vrf.c
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* PBR - vrf code
|
||||||
|
* Copyright (C) 2019 Cumulus Networks, Inc.
|
||||||
|
* Stephen Worley
|
||||||
|
*
|
||||||
|
* 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 "vrf.h"
|
||||||
|
|
||||||
|
#include "pbr_vrf.h"
|
||||||
|
#include "pbr_memory.h"
|
||||||
|
#include "pbr_map.h"
|
||||||
|
#include "pbr_debug.h"
|
||||||
|
|
||||||
|
DEFINE_MTYPE_STATIC(PBRD, PBR_MAP_VRF, "PBR Map VRF")
|
||||||
|
|
||||||
|
static struct pbr_vrf *pbr_vrf_alloc(void)
|
||||||
|
{
|
||||||
|
struct pbr_vrf *pbr_vrf;
|
||||||
|
|
||||||
|
pbr_vrf = XCALLOC(MTYPE_PBR_MAP_VRF, sizeof(struct pbr_vrf));
|
||||||
|
|
||||||
|
return pbr_vrf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pbr_vrf_free(struct pbr_vrf *pbr_vrf)
|
||||||
|
{
|
||||||
|
XFREE(MTYPE_PBR_MAP_VRF, pbr_vrf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pbr_vrf_new(struct vrf *vrf)
|
||||||
|
{
|
||||||
|
struct pbr_vrf *pbr_vrf;
|
||||||
|
|
||||||
|
DEBUGD(&pbr_dbg_event, "%s: %u (%s)", __func__, vrf->vrf_id, vrf->name);
|
||||||
|
|
||||||
|
pbr_vrf = pbr_vrf_alloc();
|
||||||
|
vrf->info = pbr_vrf;
|
||||||
|
pbr_vrf->vrf = vrf;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pbr_vrf_enable(struct vrf *vrf)
|
||||||
|
{
|
||||||
|
DEBUGD(&pbr_dbg_event, "%s: %u (%s)", __func__, vrf->vrf_id, vrf->name);
|
||||||
|
|
||||||
|
pbr_map_vrf_update(vrf->info);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pbr_vrf_disable(struct vrf *vrf)
|
||||||
|
{
|
||||||
|
DEBUGD(&pbr_dbg_event, "%s: %u (%s)", __func__, vrf->vrf_id, vrf->name);
|
||||||
|
|
||||||
|
pbr_map_vrf_update(vrf->info);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pbr_vrf_delete(struct vrf *vrf)
|
||||||
|
{
|
||||||
|
DEBUGD(&pbr_dbg_event, "%s: %u (%s)", __func__, vrf->vrf_id, vrf->name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure vrf is always marked disabled first so we handle
|
||||||
|
* pbr rules using it.
|
||||||
|
*/
|
||||||
|
assert(!vrf_is_enabled(vrf));
|
||||||
|
|
||||||
|
pbr_vrf_free(vrf->info);
|
||||||
|
vrf->info = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct pbr_vrf *pbr_vrf_lookup_by_id(vrf_id_t vrf_id)
|
||||||
|
{
|
||||||
|
struct vrf *vrf;
|
||||||
|
|
||||||
|
vrf = vrf_lookup_by_id(vrf_id);
|
||||||
|
if (vrf)
|
||||||
|
return ((struct pbr_vrf *)vrf->info);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct pbr_vrf *pbr_vrf_lookup_by_name(const char *name)
|
||||||
|
{
|
||||||
|
struct vrf *vrf;
|
||||||
|
|
||||||
|
if (!name)
|
||||||
|
name = VRF_DEFAULT_NAME;
|
||||||
|
|
||||||
|
vrf = vrf_lookup_by_name(name);
|
||||||
|
if (vrf)
|
||||||
|
return ((struct pbr_vrf *)vrf->info);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pbr_vrf_is_enabled(const struct pbr_vrf *pbr_vrf)
|
||||||
|
{
|
||||||
|
return vrf_is_enabled(pbr_vrf->vrf) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pbr_vrf_is_valid(const struct pbr_vrf *pbr_vrf)
|
||||||
|
{
|
||||||
|
if (vrf_is_backend_netns())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!pbr_vrf->vrf)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return pbr_vrf_is_enabled(pbr_vrf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pbr_vrf_init(void)
|
||||||
|
{
|
||||||
|
vrf_init(pbr_vrf_new, pbr_vrf_enable, pbr_vrf_disable, pbr_vrf_delete,
|
||||||
|
NULL);
|
||||||
|
}
|
43
pbrd/pbr_vrf.h
Normal file
43
pbrd/pbr_vrf.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* VRF library for PBR
|
||||||
|
* Copyright (C) 2019 Cumulus Networks, Inc.
|
||||||
|
* Stephen Worley
|
||||||
|
*
|
||||||
|
* 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_VRF_H__
|
||||||
|
#define __PBR_VRF_H__
|
||||||
|
|
||||||
|
struct pbr_vrf {
|
||||||
|
struct vrf *vrf;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline const char *pbr_vrf_name(const struct pbr_vrf *pbr_vrf)
|
||||||
|
{
|
||||||
|
return pbr_vrf->vrf->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline vrf_id_t pbr_vrf_id(const struct pbr_vrf *pbr_vrf)
|
||||||
|
{
|
||||||
|
return pbr_vrf->vrf->vrf_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern struct pbr_vrf *pbr_vrf_lookup_by_id(vrf_id_t vrf_id);
|
||||||
|
extern struct pbr_vrf *pbr_vrf_lookup_by_name(const char *name);
|
||||||
|
extern bool pbr_vrf_is_valid(const struct pbr_vrf *pbr_vrf);
|
||||||
|
extern bool pbr_vrf_is_enabled(const struct pbr_vrf *pbr_vrf);
|
||||||
|
|
||||||
|
extern void pbr_vrf_init(void);
|
||||||
|
#endif
|
@ -193,14 +193,17 @@ DEFPY(pbr_map_match_mark, pbr_map_match_mark_cmd,
|
|||||||
pbr_map_check(pbrms);
|
pbr_map_check(pbrms);
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define SET_VRF_EXISTS_STR \
|
||||||
|
"A `set vrf XX` command already exists, please remove that first\n"
|
||||||
|
|
||||||
DEFPY(pbr_map_nexthop_group, pbr_map_nexthop_group_cmd,
|
DEFPY(pbr_map_nexthop_group, pbr_map_nexthop_group_cmd,
|
||||||
"[no] set nexthop-group NHGNAME$name",
|
"[no] set nexthop-group NHGNAME$name",
|
||||||
NO_STR
|
NO_STR
|
||||||
"Set for the PBR-MAP\n"
|
"Set for the PBR-MAP\n"
|
||||||
"nexthop-group to use\n"
|
"nexthop-group to use\n"
|
||||||
"The name of the nexthop-group\n")
|
"The name of the nexthop-group\n")
|
||||||
{
|
{
|
||||||
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
|
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
|
||||||
struct nexthop_group_cmd *nhgc;
|
struct nexthop_group_cmd *nhgc;
|
||||||
@ -211,16 +214,22 @@ DEFPY(pbr_map_nexthop_group, pbr_map_nexthop_group_cmd,
|
|||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pbrms->vrf_lookup || pbrms->vrf_unchanged) {
|
||||||
|
vty_out(vty, SET_VRF_EXISTS_STR);
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
nhgc = nhgc_find(name);
|
nhgc = nhgc_find(name);
|
||||||
if (!nhgc) {
|
if (!nhgc) {
|
||||||
vty_out(vty, "Specified nexthop-group %s does not exist\n",
|
vty_out(vty, "Specified nexthop-group %s does not exist\n",
|
||||||
name);
|
name);
|
||||||
vty_out(vty, "PBR-MAP will not be applied until it is created\n");
|
vty_out(vty,
|
||||||
|
"PBR-MAP will not be applied until it is created\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (no) {
|
if (no) {
|
||||||
if (pbrms->nhgrp_name && strcmp(name, pbrms->nhgrp_name) == 0)
|
if (pbrms->nhgrp_name && strcmp(name, pbrms->nhgrp_name) == 0)
|
||||||
pbr_map_delete_nexthop_group(pbrms);
|
pbr_map_delete_nexthops(pbrms);
|
||||||
else {
|
else {
|
||||||
vty_out(vty,
|
vty_out(vty,
|
||||||
"Nexthop Group specified: %s does not exist to remove",
|
"Nexthop Group specified: %s does not exist to remove",
|
||||||
@ -272,6 +281,11 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd,
|
|||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pbrms->vrf_lookup || pbrms->vrf_unchanged) {
|
||||||
|
vty_out(vty, SET_VRF_EXISTS_STR);
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
if (vrf_name)
|
if (vrf_name)
|
||||||
vrf = vrf_lookup_by_name(vrf_name);
|
vrf = vrf_lookup_by_name(vrf_name);
|
||||||
else
|
else
|
||||||
@ -372,6 +386,61 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd,
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFPY(pbr_map_vrf, pbr_map_vrf_cmd,
|
||||||
|
"[no] set vrf <NAME$vrf_name|unchanged>",
|
||||||
|
NO_STR
|
||||||
|
"Set for the PBR-MAP\n"
|
||||||
|
"Specify the VRF for this map\n"
|
||||||
|
"The VRF Name\n"
|
||||||
|
"Use the interface's VRF for lookup\n")
|
||||||
|
{
|
||||||
|
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
|
||||||
|
int ret = CMD_SUCCESS;
|
||||||
|
|
||||||
|
if (no) {
|
||||||
|
pbr_map_delete_vrf(pbrms);
|
||||||
|
|
||||||
|
/* Reset all data */
|
||||||
|
pbrms->nhs_installed = false;
|
||||||
|
pbrms->vrf_name[0] = '\0';
|
||||||
|
pbrms->vrf_lookup = false;
|
||||||
|
pbrms->vrf_unchanged = false;
|
||||||
|
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pbrms->nhgrp_name || pbrms->nhg) {
|
||||||
|
vty_out(vty,
|
||||||
|
"A `set nexthop/nexthop-group XX` command already exits, please remove that first\n");
|
||||||
|
ret = CMD_WARNING_CONFIG_FAILED;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pbrms->vrf_lookup || pbrms->vrf_unchanged) {
|
||||||
|
vty_out(vty, SET_VRF_EXISTS_STR);
|
||||||
|
ret = CMD_WARNING_CONFIG_FAILED;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vrf_name) {
|
||||||
|
if (!pbr_vrf_lookup_by_name(vrf_name)) {
|
||||||
|
vty_out(vty, "Specified: %s is non-existent\n",
|
||||||
|
vrf_name);
|
||||||
|
ret = CMD_WARNING_CONFIG_FAILED;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
pbrms->vrf_lookup = true;
|
||||||
|
strlcpy(pbrms->vrf_name, vrf_name, sizeof(pbrms->vrf_name));
|
||||||
|
} else
|
||||||
|
pbrms->vrf_unchanged = true;
|
||||||
|
|
||||||
|
pbr_map_check(pbrms);
|
||||||
|
|
||||||
|
done:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
DEFPY (pbr_policy,
|
DEFPY (pbr_policy,
|
||||||
pbr_policy_cmd,
|
pbr_policy_cmd,
|
||||||
"[no] pbr-policy PBRMAP$mapname",
|
"[no] pbr-policy PBRMAP$mapname",
|
||||||
@ -500,6 +569,12 @@ DEFPY (show_pbr_map,
|
|||||||
pbrms->internal_nhg_name),
|
pbrms->internal_nhg_name),
|
||||||
pbr_nht_get_table(
|
pbr_nht_get_table(
|
||||||
pbrms->internal_nhg_name));
|
pbrms->internal_nhg_name));
|
||||||
|
} else if (pbrms->vrf_unchanged) {
|
||||||
|
vty_out(vty,
|
||||||
|
"\tVRF Unchanged (use interface vrf)\n");
|
||||||
|
} else if (pbrms->vrf_lookup) {
|
||||||
|
vty_out(vty, "\tVRF Lookup: %s\n",
|
||||||
|
pbrms->vrf_name);
|
||||||
} else {
|
} else {
|
||||||
vty_out(vty,
|
vty_out(vty,
|
||||||
"\tNexthop-Group: Unknown Installed: 0(0)\n");
|
"\tNexthop-Group: Unknown Installed: 0(0)\n");
|
||||||
@ -662,6 +737,12 @@ static int pbr_vty_map_config_write_sequence(struct vty *vty,
|
|||||||
if (pbrms->mark)
|
if (pbrms->mark)
|
||||||
vty_out(vty, " match mark %u\n", pbrms->mark);
|
vty_out(vty, " match mark %u\n", pbrms->mark);
|
||||||
|
|
||||||
|
if (pbrms->vrf_unchanged)
|
||||||
|
vty_out(vty, " set vrf unchanged\n");
|
||||||
|
|
||||||
|
if (pbrms->vrf_lookup)
|
||||||
|
vty_out(vty, " set vrf %s\n", pbrms->vrf_name);
|
||||||
|
|
||||||
if (pbrms->nhgrp_name)
|
if (pbrms->nhgrp_name)
|
||||||
vty_out(vty, " set nexthop-group %s\n", pbrms->nhgrp_name);
|
vty_out(vty, " set nexthop-group %s\n", pbrms->nhgrp_name);
|
||||||
|
|
||||||
@ -737,6 +818,7 @@ void pbr_vty_init(void)
|
|||||||
install_element(PBRMAP_NODE, &pbr_map_match_mark_cmd);
|
install_element(PBRMAP_NODE, &pbr_map_match_mark_cmd);
|
||||||
install_element(PBRMAP_NODE, &pbr_map_nexthop_group_cmd);
|
install_element(PBRMAP_NODE, &pbr_map_nexthop_group_cmd);
|
||||||
install_element(PBRMAP_NODE, &pbr_map_nexthop_cmd);
|
install_element(PBRMAP_NODE, &pbr_map_nexthop_cmd);
|
||||||
|
install_element(PBRMAP_NODE, &pbr_map_vrf_cmd);
|
||||||
install_element(VIEW_NODE, &show_pbr_cmd);
|
install_element(VIEW_NODE, &show_pbr_cmd);
|
||||||
install_element(VIEW_NODE, &show_pbr_map_cmd);
|
install_element(VIEW_NODE, &show_pbr_map_cmd);
|
||||||
install_element(VIEW_NODE, &show_pbr_interface_cmd);
|
install_element(VIEW_NODE, &show_pbr_interface_cmd);
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include "pbr_memory.h"
|
#include "pbr_memory.h"
|
||||||
#include "pbr_zebra.h"
|
#include "pbr_zebra.h"
|
||||||
#include "pbr_debug.h"
|
#include "pbr_debug.h"
|
||||||
|
#include "pbr_vrf.h"
|
||||||
|
|
||||||
DEFINE_MTYPE_STATIC(PBRD, PBR_INTERFACE, "PBR Interface")
|
DEFINE_MTYPE_STATIC(PBRD, PBR_INTERFACE, "PBR Interface")
|
||||||
|
|
||||||
@ -67,8 +68,11 @@ int pbr_ifp_create(struct interface *ifp)
|
|||||||
if (!ifp->info)
|
if (!ifp->info)
|
||||||
pbr_if_new(ifp);
|
pbr_if_new(ifp);
|
||||||
|
|
||||||
|
/* Update nexthops tracked from a `set nexthop` command */
|
||||||
pbr_nht_nexthop_interface_update(ifp);
|
pbr_nht_nexthop_interface_update(ifp);
|
||||||
|
|
||||||
|
pbr_map_policy_interface_update(ifp, true);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,6 +81,8 @@ int pbr_ifp_destroy(struct interface *ifp)
|
|||||||
DEBUGD(&pbr_dbg_zebra,
|
DEBUGD(&pbr_dbg_zebra,
|
||||||
"%s: %s", __PRETTY_FUNCTION__, ifp->name);
|
"%s: %s", __PRETTY_FUNCTION__, ifp->name);
|
||||||
|
|
||||||
|
pbr_map_policy_interface_update(ifp, false);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,6 +139,29 @@ int pbr_ifp_down(struct interface *ifp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int interface_vrf_update(ZAPI_CALLBACK_ARGS)
|
||||||
|
{
|
||||||
|
struct interface *ifp;
|
||||||
|
vrf_id_t new_vrf_id;
|
||||||
|
|
||||||
|
ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,
|
||||||
|
&new_vrf_id);
|
||||||
|
|
||||||
|
if (!ifp) {
|
||||||
|
DEBUGD(&pbr_dbg_zebra, "%s: VRF change interface not found",
|
||||||
|
__func__);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUGD(&pbr_dbg_zebra, "%s: %s VRF change %u -> %u", __func__,
|
||||||
|
ifp->name, vrf_id, new_vrf_id);
|
||||||
|
|
||||||
|
if_update_to_new_vrf(ifp, new_vrf_id);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int route_notify_owner(ZAPI_CALLBACK_ARGS)
|
static int route_notify_owner(ZAPI_CALLBACK_ARGS)
|
||||||
{
|
{
|
||||||
struct prefix p;
|
struct prefix p;
|
||||||
@ -421,6 +450,7 @@ void pbr_zebra_init(void)
|
|||||||
zclient->zebra_connected = zebra_connected;
|
zclient->zebra_connected = zebra_connected;
|
||||||
zclient->interface_address_add = interface_address_add;
|
zclient->interface_address_add = interface_address_add;
|
||||||
zclient->interface_address_delete = interface_address_delete;
|
zclient->interface_address_delete = interface_address_delete;
|
||||||
|
zclient->interface_vrf_update = interface_vrf_update;
|
||||||
zclient->route_notify_owner = route_notify_owner;
|
zclient->route_notify_owner = route_notify_owner;
|
||||||
zclient->rule_notify_owner = rule_notify_owner;
|
zclient->rule_notify_owner = rule_notify_owner;
|
||||||
zclient->nexthop_update = pbr_zebra_nexthop_update;
|
zclient->nexthop_update = pbr_zebra_nexthop_update;
|
||||||
@ -483,6 +513,26 @@ static void pbr_encode_pbr_map_sequence_prefix(struct stream *s,
|
|||||||
stream_put(s, &p->u.prefix, prefix_blen(p));
|
stream_put(s, &p->u.prefix, prefix_blen(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pbr_encode_pbr_map_sequence_vrf(struct stream *s,
|
||||||
|
const struct pbr_map_sequence *pbrms,
|
||||||
|
const struct interface *ifp)
|
||||||
|
{
|
||||||
|
struct pbr_vrf *pbr_vrf;
|
||||||
|
|
||||||
|
if (pbrms->vrf_unchanged)
|
||||||
|
pbr_vrf = pbr_vrf_lookup_by_id(ifp->vrf_id);
|
||||||
|
else
|
||||||
|
pbr_vrf = pbr_vrf_lookup_by_name(pbrms->vrf_name);
|
||||||
|
|
||||||
|
if (!pbr_vrf) {
|
||||||
|
DEBUGD(&pbr_dbg_zebra, "%s: VRF not found", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream_putl(s, pbr_vrf->vrf->data.l.table_id);
|
||||||
|
}
|
||||||
|
|
||||||
static void pbr_encode_pbr_map_sequence(struct stream *s,
|
static void pbr_encode_pbr_map_sequence(struct stream *s,
|
||||||
struct pbr_map_sequence *pbrms,
|
struct pbr_map_sequence *pbrms,
|
||||||
struct interface *ifp)
|
struct interface *ifp)
|
||||||
@ -501,7 +551,10 @@ static void pbr_encode_pbr_map_sequence(struct stream *s,
|
|||||||
pbr_encode_pbr_map_sequence_prefix(s, pbrms->dst, family);
|
pbr_encode_pbr_map_sequence_prefix(s, pbrms->dst, family);
|
||||||
stream_putw(s, 0); /* dst port */
|
stream_putw(s, 0); /* dst port */
|
||||||
stream_putl(s, pbrms->mark);
|
stream_putl(s, pbrms->mark);
|
||||||
if (pbrms->nhgrp_name)
|
|
||||||
|
if (pbrms->vrf_unchanged || pbrms->vrf_lookup)
|
||||||
|
pbr_encode_pbr_map_sequence_vrf(s, pbrms, ifp);
|
||||||
|
else if (pbrms->nhgrp_name)
|
||||||
stream_putl(s, pbr_nht_get_table(pbrms->nhgrp_name));
|
stream_putl(s, pbr_nht_get_table(pbrms->nhgrp_name));
|
||||||
else if (pbrms->nhg)
|
else if (pbrms->nhg)
|
||||||
stream_putl(s, pbr_nht_get_table(pbrms->internal_nhg_name));
|
stream_putl(s, pbr_nht_get_table(pbrms->internal_nhg_name));
|
||||||
|
@ -20,6 +20,7 @@ pbrd_libpbr_a_SOURCES = \
|
|||||||
pbrd/pbr_memory.c \
|
pbrd/pbr_memory.c \
|
||||||
pbrd/pbr_nht.c \
|
pbrd/pbr_nht.c \
|
||||||
pbrd/pbr_debug.c \
|
pbrd/pbr_debug.c \
|
||||||
|
pbrd/pbr_vrf.c \
|
||||||
# end
|
# end
|
||||||
|
|
||||||
noinst_HEADERS += \
|
noinst_HEADERS += \
|
||||||
@ -29,6 +30,7 @@ noinst_HEADERS += \
|
|||||||
pbrd/pbr_vty.h \
|
pbrd/pbr_vty.h \
|
||||||
pbrd/pbr_zebra.h \
|
pbrd/pbr_zebra.h \
|
||||||
pbrd/pbr_debug.h \
|
pbrd/pbr_debug.h \
|
||||||
|
pbrd/pbr_vrf.h \
|
||||||
# end
|
# end
|
||||||
|
|
||||||
pbrd/pbr_vty_clippy.c: $(CLIPPY_DEPS)
|
pbrd/pbr_vty_clippy.c: $(CLIPPY_DEPS)
|
||||||
|
Loading…
Reference in New Issue
Block a user