mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-07-09 18:50:39 +00:00
pbrd: implement set *
and match *
config replacement
Implement the ability to replace any existing `set *` or `match` with another one or adding more config without having to first delete the original config already there. Before, we needed to constantly execute a `no` command for everything to remove the rule before making changes to it. With this patch, you can replace configs on individual sequences much easier. Signed-off-by: Stephen Worley <sworley@cumulusnetworks.com>
This commit is contained in:
parent
10fcd2a2a6
commit
f143cffac2
@ -145,7 +145,7 @@ static bool pbr_map_interface_is_valid(const struct pbr_map_interface *pmi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void pbr_map_pbrms_update_common(struct pbr_map_sequence *pbrms,
|
static void pbr_map_pbrms_update_common(struct pbr_map_sequence *pbrms,
|
||||||
bool install)
|
bool install, bool changed)
|
||||||
{
|
{
|
||||||
struct pbr_map *pbrm;
|
struct pbr_map *pbrm;
|
||||||
struct listnode *node;
|
struct listnode *node;
|
||||||
@ -161,19 +161,19 @@ static void pbr_map_pbrms_update_common(struct pbr_map_sequence *pbrms,
|
|||||||
if (install && !pbr_map_interface_is_valid(pmi))
|
if (install && !pbr_map_interface_is_valid(pmi))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
pbr_send_pbr_map(pbrms, pmi, install);
|
pbr_send_pbr_map(pbrms, pmi, install, changed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pbr_map_pbrms_install(struct pbr_map_sequence *pbrms)
|
static void pbr_map_pbrms_install(struct pbr_map_sequence *pbrms, bool changed)
|
||||||
{
|
{
|
||||||
pbr_map_pbrms_update_common(pbrms, true);
|
pbr_map_pbrms_update_common(pbrms, true, changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pbr_map_pbrms_uninstall(struct pbr_map_sequence *pbrms)
|
static void pbr_map_pbrms_uninstall(struct pbr_map_sequence *pbrms)
|
||||||
{
|
{
|
||||||
pbr_map_pbrms_update_common(pbrms, false);
|
pbr_map_pbrms_update_common(pbrms, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *const pbr_map_reason_str[] = {
|
static const char *const pbr_map_reason_str[] = {
|
||||||
@ -292,7 +292,7 @@ void pbr_map_policy_interface_update(const struct interface *ifp, bool state_up)
|
|||||||
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))
|
for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi))
|
||||||
if (pmi->ifp == ifp && pbr_map_interface_is_valid(pmi))
|
if (pmi->ifp == ifp && pbr_map_interface_is_valid(pmi))
|
||||||
pbr_send_pbr_map(pbrms, pmi, state_up);
|
pbr_send_pbr_map(pbrms, pmi, state_up, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pbrms_vrf_update(struct pbr_map_sequence *pbrms,
|
static void pbrms_vrf_update(struct pbr_map_sequence *pbrms,
|
||||||
@ -306,7 +306,7 @@ static void pbrms_vrf_update(struct pbr_map_sequence *pbrms,
|
|||||||
DEBUGD(&pbr_dbg_map, "\tSeq %u uses vrf %s (%u), updating map",
|
DEBUGD(&pbr_dbg_map, "\tSeq %u uses vrf %s (%u), updating map",
|
||||||
pbrms->seqno, vrf_name, pbr_vrf_id(pbr_vrf));
|
pbrms->seqno, vrf_name, pbr_vrf_id(pbr_vrf));
|
||||||
|
|
||||||
pbr_map_check(pbrms);
|
pbr_map_check(pbrms, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -360,7 +360,7 @@ extern void pbr_map_delete(struct pbr_map_sequence *pbrms)
|
|||||||
pbrm = pbrms->parent;
|
pbrm = pbrms->parent;
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi))
|
for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi))
|
||||||
pbr_send_pbr_map(pbrms, pmi, false);
|
pbr_send_pbr_map(pbrms, pmi, false, false);
|
||||||
|
|
||||||
if (pbrms->nhg)
|
if (pbrms->nhg)
|
||||||
pbr_nht_delete_individual_nexthop(pbrms);
|
pbr_nht_delete_individual_nexthop(pbrms);
|
||||||
@ -619,7 +619,7 @@ void pbr_map_schedule_policy_from_nhg(const char *nh_group)
|
|||||||
&& (strcmp(nh_group, pbrms->nhgrp_name) == 0)) {
|
&& (strcmp(nh_group, pbrms->nhgrp_name) == 0)) {
|
||||||
pbrms->nhs_installed = true;
|
pbrms->nhs_installed = true;
|
||||||
|
|
||||||
pbr_map_check(pbrms);
|
pbr_map_check(pbrms, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pbrms->nhg
|
if (pbrms->nhg
|
||||||
@ -627,7 +627,7 @@ void pbr_map_schedule_policy_from_nhg(const char *nh_group)
|
|||||||
== 0)) {
|
== 0)) {
|
||||||
pbrms->nhs_installed = true;
|
pbrms->nhs_installed = true;
|
||||||
|
|
||||||
pbr_map_check(pbrms);
|
pbr_map_check(pbrms, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -656,7 +656,8 @@ void pbr_map_policy_install(const char *name)
|
|||||||
pbrms->seqno);
|
pbrms->seqno);
|
||||||
for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi))
|
for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi))
|
||||||
if (pbr_map_interface_is_valid(pmi))
|
if (pbr_map_interface_is_valid(pmi))
|
||||||
pbr_send_pbr_map(pbrms, pmi, true);
|
pbr_send_pbr_map(pbrms, pmi, true,
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -668,7 +669,7 @@ void pbr_map_policy_delete(struct pbr_map *pbrm, struct pbr_map_interface *pmi)
|
|||||||
|
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms))
|
for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms))
|
||||||
pbr_send_pbr_map(pbrms, pmi, false);
|
pbr_send_pbr_map(pbrms, pmi, false, false);
|
||||||
|
|
||||||
pmi->delete = true;
|
pmi->delete = true;
|
||||||
}
|
}
|
||||||
@ -710,13 +711,13 @@ void pbr_map_check_nh_group_change(const char *nh_group)
|
|||||||
pbrm->incoming, inode,
|
pbrm->incoming, inode,
|
||||||
pmi))
|
pmi))
|
||||||
pbr_send_pbr_map(pbrms, pmi,
|
pbr_send_pbr_map(pbrms, pmi,
|
||||||
false);
|
false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pbr_map_check(struct pbr_map_sequence *pbrms)
|
void pbr_map_check(struct pbr_map_sequence *pbrms, bool changed)
|
||||||
{
|
{
|
||||||
struct pbr_map *pbrm;
|
struct pbr_map *pbrm;
|
||||||
bool install;
|
bool install;
|
||||||
@ -741,7 +742,7 @@ void pbr_map_check(struct pbr_map_sequence *pbrms)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (install)
|
if (install)
|
||||||
pbr_map_pbrms_install(pbrms);
|
pbr_map_pbrms_install(pbrms, changed);
|
||||||
else
|
else
|
||||||
pbr_map_pbrms_uninstall(pbrms);
|
pbr_map_pbrms_uninstall(pbrms);
|
||||||
}
|
}
|
||||||
@ -755,7 +756,7 @@ void pbr_map_install(struct pbr_map *pbrm)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms))
|
for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms))
|
||||||
pbr_map_pbrms_install(pbrms);
|
pbr_map_pbrms_install(pbrms, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pbr_map_init(void)
|
void pbr_map_init(void)
|
||||||
|
@ -182,7 +182,15 @@ extern void pbr_map_init(void);
|
|||||||
|
|
||||||
extern bool pbr_map_check_valid(const char *name);
|
extern bool pbr_map_check_valid(const char *name);
|
||||||
|
|
||||||
extern void pbr_map_check(struct pbr_map_sequence *pbrms);
|
/**
|
||||||
|
* Re-check the pbr map for validity.
|
||||||
|
*
|
||||||
|
* Install if valid, remove if not.
|
||||||
|
*
|
||||||
|
* If changed is set, the config on the on the map has changed somewhere
|
||||||
|
* and the rules need to be replaced if valid.
|
||||||
|
*/
|
||||||
|
extern void pbr_map_check(struct pbr_map_sequence *pbrms, bool changed);
|
||||||
extern void pbr_map_check_nh_group_change(const char *nh_group);
|
extern void pbr_map_check_nh_group_change(const char *nh_group);
|
||||||
extern void pbr_map_reason_string(unsigned int reason, char *buf, int size);
|
extern void pbr_map_reason_string(unsigned int reason, char *buf, int size);
|
||||||
|
|
||||||
|
@ -510,12 +510,26 @@ char *pbr_nht_nexthop_make_name(char *name, size_t l,
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pbr_nht_add_individual_nexthop(struct pbr_map_sequence *pbrms)
|
void pbr_nht_add_individual_nexthop(struct pbr_map_sequence *pbrms,
|
||||||
|
const struct nexthop *nhop)
|
||||||
{
|
{
|
||||||
struct pbr_nexthop_group_cache *pnhgc;
|
struct pbr_nexthop_group_cache *pnhgc;
|
||||||
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 lookup;
|
struct pbr_nexthop_cache lookup;
|
||||||
|
struct nexthop *nh;
|
||||||
|
char buf[PBR_NHC_NAMELEN];
|
||||||
|
|
||||||
|
pbrms->nhg = nexthop_group_new();
|
||||||
|
pbrms->internal_nhg_name = XSTRDUP(
|
||||||
|
MTYPE_TMP,
|
||||||
|
pbr_nht_nexthop_make_name(pbrms->parent->name, PBR_NHC_NAMELEN,
|
||||||
|
pbrms->seqno, buf));
|
||||||
|
|
||||||
|
nh = nexthop_new();
|
||||||
|
memcpy(nh, nhop, sizeof(*nh));
|
||||||
|
|
||||||
|
nexthop_group_add_sorted(pbrms->nhg, nh);
|
||||||
|
|
||||||
memset(&find, 0, sizeof(find));
|
memset(&find, 0, sizeof(find));
|
||||||
pbr_nht_nexthop_make_name(pbrms->parent->name, PBR_NHC_NAMELEN,
|
pbr_nht_nexthop_make_name(pbrms->parent->name, PBR_NHC_NAMELEN,
|
||||||
@ -539,7 +553,7 @@ void pbr_nht_add_individual_nexthop(struct pbr_map_sequence *pbrms)
|
|||||||
pbr_nht_install_nexthop_group(pnhgc, *pbrms->nhg);
|
pbr_nht_install_nexthop_group(pnhgc, *pbrms->nhg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pbr_nht_delete_individual_nexthop(struct pbr_map_sequence *pbrms)
|
static void pbr_nht_release_individual_nexthop(struct pbr_map_sequence *pbrms)
|
||||||
{
|
{
|
||||||
struct pbr_nexthop_group_cache *pnhgc;
|
struct pbr_nexthop_group_cache *pnhgc;
|
||||||
struct pbr_nexthop_group_cache find;
|
struct pbr_nexthop_group_cache find;
|
||||||
@ -548,8 +562,6 @@ void pbr_nht_delete_individual_nexthop(struct pbr_map_sequence *pbrms)
|
|||||||
struct nexthop *nh;
|
struct nexthop *nh;
|
||||||
enum nexthop_types_t nh_type = 0;
|
enum nexthop_types_t nh_type = 0;
|
||||||
|
|
||||||
pbr_map_delete_nexthops(pbrms);
|
|
||||||
|
|
||||||
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);
|
||||||
pnhgc = hash_lookup(pbr_nhg_hash, &find);
|
pnhgc = hash_lookup(pbr_nhg_hash, &find);
|
||||||
@ -570,6 +582,13 @@ void pbr_nht_delete_individual_nexthop(struct pbr_map_sequence *pbrms)
|
|||||||
XFREE(MTYPE_TMP, pbrms->internal_nhg_name);
|
XFREE(MTYPE_TMP, pbrms->internal_nhg_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pbr_nht_delete_individual_nexthop(struct pbr_map_sequence *pbrms)
|
||||||
|
{
|
||||||
|
pbr_map_delete_nexthops(pbrms);
|
||||||
|
|
||||||
|
pbr_nht_release_individual_nexthop(pbrms);
|
||||||
|
}
|
||||||
|
|
||||||
struct pbr_nexthop_group_cache *pbr_nht_add_group(const char *name)
|
struct pbr_nexthop_group_cache *pbr_nht_add_group(const char *name)
|
||||||
{
|
{
|
||||||
struct nexthop *nhop;
|
struct nexthop *nhop;
|
||||||
|
@ -88,7 +88,8 @@ 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_change_group(const char *name);
|
||||||
extern void pbr_nht_delete_group(const char *name);
|
extern void pbr_nht_delete_group(const char *name);
|
||||||
|
|
||||||
extern void pbr_nht_add_individual_nexthop(struct pbr_map_sequence *pbrms);
|
extern void pbr_nht_add_individual_nexthop(struct pbr_map_sequence *pbrms,
|
||||||
|
const struct nexthop *nhop);
|
||||||
extern void pbr_nht_delete_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
|
* Given the tableid of the installed default
|
||||||
|
196
pbrd/pbr_vty.c
196
pbrd/pbr_vty.c
@ -142,18 +142,14 @@ DEFPY(pbr_map_match_src, pbr_map_match_src_cmd,
|
|||||||
if (pbrms->src) {
|
if (pbrms->src) {
|
||||||
if (prefix_same(pbrms->src, prefix))
|
if (prefix_same(pbrms->src, prefix))
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
|
} else
|
||||||
vty_out(vty,
|
|
||||||
"A `match src-ip XX` command already exists, please remove that first\n");
|
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
pbrms->src = prefix_new();
|
pbrms->src = prefix_new();
|
||||||
|
|
||||||
prefix_copy(pbrms->src, prefix);
|
prefix_copy(pbrms->src, prefix);
|
||||||
} else
|
} else
|
||||||
prefix_free(&pbrms->src);
|
prefix_free(&pbrms->src);
|
||||||
|
|
||||||
pbr_map_check(pbrms);
|
pbr_map_check(pbrms, true);
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -174,18 +170,14 @@ DEFPY(pbr_map_match_dst, pbr_map_match_dst_cmd,
|
|||||||
if (pbrms->dst) {
|
if (pbrms->dst) {
|
||||||
if (prefix_same(pbrms->dst, prefix))
|
if (prefix_same(pbrms->dst, prefix))
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
|
} else
|
||||||
vty_out(vty,
|
|
||||||
"A `match dst-ip XX` command already exists, please remove that first\n");
|
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
pbrms->dst = prefix_new();
|
pbrms->dst = prefix_new();
|
||||||
|
|
||||||
prefix_copy(pbrms->dst, prefix);
|
prefix_copy(pbrms->dst, prefix);
|
||||||
} else
|
} else
|
||||||
prefix_free(&pbrms->dst);
|
prefix_free(&pbrms->dst);
|
||||||
|
|
||||||
pbr_map_check(pbrms);
|
pbr_map_check(pbrms, true);
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -205,26 +197,49 @@ DEFPY(pbr_map_match_mark, pbr_map_match_mark_cmd,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!no) {
|
if (!no) {
|
||||||
if (pbrms->mark) {
|
if (pbrms->mark)
|
||||||
if (pbrms->mark == (uint32_t)mark)
|
if (pbrms->mark == (uint32_t)mark)
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
|
|
||||||
vty_out(vty,
|
|
||||||
"A `match mark XX` command already exists, please remove that first\n");
|
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
pbrms->mark = (uint32_t)mark;
|
pbrms->mark = (uint32_t)mark;
|
||||||
} else
|
} else
|
||||||
pbrms->mark = 0;
|
pbrms->mark = 0;
|
||||||
|
|
||||||
pbr_map_check(pbrms);
|
pbr_map_check(pbrms, true);
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SET_VRF_EXISTS_STR \
|
static void pbrms_clear_set_vrf_config(struct pbr_map_sequence *pbrms)
|
||||||
"A `set vrf XX` command already exists, please remove that first\n"
|
{
|
||||||
|
if (pbrms->vrf_lookup || pbrms->vrf_unchanged) {
|
||||||
|
pbr_map_delete_vrf(pbrms);
|
||||||
|
pbrms->vrf_name[0] = '\0';
|
||||||
|
pbrms->vrf_lookup = false;
|
||||||
|
pbrms->vrf_unchanged = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pbrms_clear_set_nhg_config(struct pbr_map_sequence *pbrms)
|
||||||
|
{
|
||||||
|
if (pbrms->nhgrp_name)
|
||||||
|
pbr_map_delete_nexthops(pbrms);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pbrms_clear_set_nexthop_config(struct pbr_map_sequence *pbrms)
|
||||||
|
{
|
||||||
|
if (pbrms->nhg)
|
||||||
|
pbr_nht_delete_individual_nexthop(pbrms);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pbrms_clear_set_config(struct pbr_map_sequence *pbrms)
|
||||||
|
{
|
||||||
|
pbrms_clear_set_vrf_config(pbrms);
|
||||||
|
pbrms_clear_set_nhg_config(pbrms);
|
||||||
|
pbrms_clear_set_nexthop_config(pbrms);
|
||||||
|
|
||||||
|
pbrms->nhs_installed = false;
|
||||||
|
}
|
||||||
|
|
||||||
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",
|
||||||
@ -236,17 +251,6 @@ DEFPY(pbr_map_nexthop_group, pbr_map_nexthop_group_cmd,
|
|||||||
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;
|
||||||
|
|
||||||
if (pbrms->nhg) {
|
|
||||||
vty_out(vty,
|
|
||||||
"A `set nexthop XX` command already exists, please remove that first\n");
|
|
||||||
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",
|
||||||
@ -255,28 +259,21 @@ DEFPY(pbr_map_nexthop_group, pbr_map_nexthop_group_cmd,
|
|||||||
"PBR-MAP will not be applied until it is created\n");
|
"PBR-MAP will not be applied until it is created\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (no) {
|
if (no && pbrms->nhgrp_name && strcmp(name, pbrms->nhgrp_name) != 0) {
|
||||||
if (pbrms->nhgrp_name && strcmp(name, pbrms->nhgrp_name) == 0)
|
|
||||||
pbr_map_delete_nexthops(pbrms);
|
|
||||||
else {
|
|
||||||
vty_out(vty,
|
vty_out(vty,
|
||||||
"Nexthop Group specified: %s does not exist to remove\n",
|
"Nexthop Group specified: %s does not exist to remove\n",
|
||||||
name);
|
name);
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (pbrms->nhgrp_name) {
|
|
||||||
if (strcmp(name, pbrms->nhgrp_name) != 0) {
|
|
||||||
vty_out(vty,
|
|
||||||
"Please delete current nexthop group before modifying current one\n");
|
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (pbrms->nhgrp_name && strcmp(name, pbrms->nhgrp_name) == 0)
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
|
||||||
|
/* This is new/replacement config */
|
||||||
|
pbrms_clear_set_config(pbrms);
|
||||||
|
|
||||||
pbrms->nhgrp_name = XSTRDUP(MTYPE_TMP, name);
|
pbrms->nhgrp_name = XSTRDUP(MTYPE_TMP, name);
|
||||||
pbr_map_check(pbrms);
|
pbr_map_check(pbrms, true);
|
||||||
}
|
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -301,18 +298,7 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd,
|
|||||||
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
|
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
|
||||||
struct vrf *vrf;
|
struct vrf *vrf;
|
||||||
struct nexthop nhop;
|
struct nexthop nhop;
|
||||||
struct nexthop *nh;
|
struct nexthop *nh = NULL;
|
||||||
|
|
||||||
if (pbrms->nhgrp_name) {
|
|
||||||
vty_out(vty,
|
|
||||||
"Please unconfigure the nexthop group before adding an individual nexthop\n");
|
|
||||||
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);
|
||||||
@ -362,45 +348,23 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd,
|
|||||||
|
|
||||||
if (pbrms->nhg)
|
if (pbrms->nhg)
|
||||||
nh = nexthop_exists(pbrms->nhg, &nhop);
|
nh = nexthop_exists(pbrms->nhg, &nhop);
|
||||||
else {
|
|
||||||
char buf[PBR_NHC_NAMELEN];
|
|
||||||
|
|
||||||
if (no) {
|
if (no && !nh) {
|
||||||
vty_out(vty, "No nexthops to delete\n");
|
vty_out(vty, "No nexthops to delete\n");
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
pbrms->nhg = nexthop_group_new();
|
if (nh) /* Same config re-entered */
|
||||||
pbrms->internal_nhg_name =
|
goto done;
|
||||||
XSTRDUP(MTYPE_TMP,
|
|
||||||
pbr_nht_nexthop_make_name(pbrms->parent->name,
|
|
||||||
PBR_NHC_NAMELEN,
|
|
||||||
pbrms->seqno,
|
|
||||||
buf));
|
|
||||||
nh = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (no) {
|
/* This is new/replacement config */
|
||||||
if (nh)
|
pbrms_clear_set_config(pbrms);
|
||||||
pbr_nht_delete_individual_nexthop(pbrms);
|
|
||||||
} else if (!nh) {
|
|
||||||
|
|
||||||
if (pbrms->nhg->nexthop) {
|
pbr_nht_add_individual_nexthop(pbrms, &nhop);
|
||||||
vty_out(vty,
|
|
||||||
"If you would like more than one nexthop please use nexthop-groups\n");
|
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* must be adding new nexthop since !no and !nexthop_exists */
|
pbr_map_check(pbrms, true);
|
||||||
nh = nexthop_new();
|
|
||||||
|
|
||||||
memcpy(nh, &nhop, sizeof(nhop));
|
|
||||||
_nexthop_add(&pbrms->nhg->nexthop, nh);
|
|
||||||
|
|
||||||
pbr_nht_add_individual_nexthop(pbrms);
|
|
||||||
pbr_map_check(pbrms);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
done:
|
||||||
if (nhop.type == NEXTHOP_TYPE_IFINDEX
|
if (nhop.type == NEXTHOP_TYPE_IFINDEX
|
||||||
|| (nhop.type == NEXTHOP_TYPE_IPV6_IFINDEX
|
|| (nhop.type == NEXTHOP_TYPE_IPV6_IFINDEX
|
||||||
&& IN6_IS_ADDR_LINKLOCAL(&nhop.gate.ipv6))) {
|
&& IN6_IS_ADDR_LINKLOCAL(&nhop.gate.ipv6))) {
|
||||||
@ -425,54 +389,24 @@ DEFPY(pbr_map_vrf, pbr_map_vrf_cmd,
|
|||||||
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
|
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
|
||||||
|
|
||||||
if (no) {
|
if (no) {
|
||||||
pbr_map_delete_vrf(pbrms);
|
|
||||||
|
|
||||||
/* Reset all data */
|
/* Reset all data */
|
||||||
pbrms->nhs_installed = false;
|
pbrms_clear_set_config(pbrms);
|
||||||
pbrms->vrf_name[0] = '\0';
|
|
||||||
pbrms->vrf_lookup = false;
|
|
||||||
pbrms->vrf_unchanged = false;
|
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pbrms->nhgrp_name || pbrms->nhg) {
|
|
||||||
vty_out(vty,
|
|
||||||
"A `set nexthop/nexthop-group XX` command already exits, please remove that first\n");
|
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine if a set vrf * command already exists.
|
* If an equivalent set vrf * exists, just return success.
|
||||||
*
|
|
||||||
* If its equivalent, just return success.
|
|
||||||
*
|
|
||||||
* Else, return failure, we don't allow atomic swaps yet.
|
|
||||||
*/
|
*/
|
||||||
if (vrf_name && pbrms->vrf_lookup) {
|
if (vrf_name && pbrms->vrf_lookup
|
||||||
/* New vrf specified and one already exists */
|
&& strncmp(pbrms->vrf_name, vrf_name, sizeof(pbrms->vrf_name)) == 0)
|
||||||
|
return CMD_SUCCESS;
|
||||||
/* Is this vrf different from one already configured? */
|
else if (!vrf_name && pbrms->vrf_unchanged) /* Unchanged already set */
|
||||||
if (strncmp(pbrms->vrf_name, vrf_name, sizeof(pbrms->vrf_name))
|
|
||||||
!= 0)
|
|
||||||
goto vrf_exists;
|
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
|
|
||||||
} else if (!vrf_name && pbrms->vrf_unchanged) {
|
/* This is new/replacement config */
|
||||||
/* Unchanged specified and unchanged already exists */
|
pbrms_clear_set_config(pbrms);
|
||||||
return CMD_SUCCESS;
|
|
||||||
|
|
||||||
} else if (vrf_name && pbrms->vrf_unchanged) {
|
|
||||||
/* New vrf specified and unchanged is already set */
|
|
||||||
goto vrf_exists;
|
|
||||||
|
|
||||||
} else if (!vrf_name && pbrms->vrf_lookup) {
|
|
||||||
/* Unchanged specified and vrf to lookup already exists */
|
|
||||||
goto vrf_exists;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create new lookup VRF or Unchanged */
|
|
||||||
if (vrf_name) {
|
if (vrf_name) {
|
||||||
if (!pbr_vrf_lookup_by_name(vrf_name)) {
|
if (!pbr_vrf_lookup_by_name(vrf_name)) {
|
||||||
vty_out(vty, "Specified: %s is non-existent\n",
|
vty_out(vty, "Specified: %s is non-existent\n",
|
||||||
@ -485,13 +419,9 @@ DEFPY(pbr_map_vrf, pbr_map_vrf_cmd,
|
|||||||
} else
|
} else
|
||||||
pbrms->vrf_unchanged = true;
|
pbrms->vrf_unchanged = true;
|
||||||
|
|
||||||
pbr_map_check(pbrms);
|
pbr_map_check(pbrms, true);
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
|
|
||||||
vrf_exists:
|
|
||||||
vty_out(vty, SET_VRF_EXISTS_STR);
|
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFPY (pbr_policy,
|
DEFPY (pbr_policy,
|
||||||
|
@ -548,7 +548,7 @@ static void pbr_encode_pbr_map_sequence(struct stream *s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void pbr_send_pbr_map(struct pbr_map_sequence *pbrms,
|
void pbr_send_pbr_map(struct pbr_map_sequence *pbrms,
|
||||||
struct pbr_map_interface *pmi, bool install)
|
struct pbr_map_interface *pmi, bool install, bool changed)
|
||||||
{
|
{
|
||||||
struct pbr_map *pbrm = pbrms->parent;
|
struct pbr_map *pbrm = pbrms->parent;
|
||||||
struct stream *s;
|
struct stream *s;
|
||||||
@ -560,11 +560,13 @@ void pbr_send_pbr_map(struct pbr_map_sequence *pbrms,
|
|||||||
pbrm->name, install, is_installed);
|
pbrm->name, install, is_installed);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we are installed and asked to do so again
|
* If we are installed and asked to do so again and the config
|
||||||
* just return. If we are not installed and asked
|
* has not changed, just return.
|
||||||
|
*
|
||||||
|
* If we are not installed and asked
|
||||||
* and asked to delete just return;
|
* and asked to delete just return;
|
||||||
*/
|
*/
|
||||||
if (install && is_installed)
|
if (install && is_installed && !changed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!install && !is_installed)
|
if (!install && !is_installed)
|
||||||
|
@ -36,7 +36,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_rnh(struct nexthop *nhop, bool reg);
|
||||||
|
|
||||||
extern void pbr_send_pbr_map(struct pbr_map_sequence *pbrms,
|
extern void pbr_send_pbr_map(struct pbr_map_sequence *pbrms,
|
||||||
struct pbr_map_interface *pmi, bool install);
|
struct pbr_map_interface *pmi, bool install,
|
||||||
|
bool changed);
|
||||||
|
|
||||||
extern struct pbr_interface *pbr_if_new(struct interface *ifp);
|
extern struct pbr_interface *pbr_if_new(struct interface *ifp);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user