summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilippe Guibert <philippe.guibert@6wind.com>2018-06-19 15:02:26 +0200
committerPhilippe Guibert <philippe.guibert@6wind.com>2018-06-28 11:08:58 +0200
commit56707a36d00eaa26857eb8c96021d664366063c6 (patch)
treef3a5446a80987b601e487d54c0c4e7fba8f4b42c
parentbgpd: enumerate support for dscp values (diff)
downloadfrr-56707a36d00eaa26857eb8c96021d664366063c6.tar.xz
frr-56707a36d00eaa26857eb8c96021d664366063c6.zip
bgpd: introduce recursive operations for or flowspec operations
So as to add or remove entries with flowspec or operations like tcp flags or dscp enum list, a mechanism is put in place that adds recursivity. Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
-rw-r--r--bgpd/bgp_pbr.c137
1 files changed, 111 insertions, 26 deletions
diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c
index 539c421e5..cfea83242 100644
--- a/bgpd/bgp_pbr.c
+++ b/bgpd/bgp_pbr.c
@@ -216,6 +216,7 @@ struct bgp_pbr_filter {
*/
struct bgp_pbr_or_filter {
struct list *tcpflags;
+ struct list *dscp;
};
/* TCP : FIN and SYN -> val = ALL; mask = 3
@@ -1303,25 +1304,65 @@ static void bgp_pbr_policyroute_remove_from_zebra_unit(struct bgp *bgp,
}
}
+static void bgp_pbr_policyroute_remove_from_zebra_recursive(struct bgp *bgp,
+ struct bgp_info *binfo,
+ struct bgp_pbr_filter *bpf,
+ struct bgp_pbr_or_filter *bpof,
+ uint8_t type_entry)
+{
+ struct listnode *node, *nnode;
+ struct bgp_pbr_val_mask *valmask;
+ uint8_t next_type_entry;
+ struct list *orig_list;
+ struct bgp_pbr_val_mask **target_val;
+
+ if (type_entry == 0)
+ return bgp_pbr_policyroute_remove_from_zebra_unit(bgp,
+ binfo, bpf);
+ if (type_entry == FLOWSPEC_TCP_FLAGS && bpof->tcpflags) {
+ next_type_entry = FLOWSPEC_DSCP;
+ orig_list = bpof->tcpflags;
+ target_val = &bpf->tcp_flags;
+ } else if (type_entry == FLOWSPEC_DSCP && bpof->dscp) {
+ next_type_entry = 0;
+ orig_list = bpof->dscp;
+ target_val = &bpf->dscp;
+ } else {
+ return bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
+ bpf, bpof, 0);
+ }
+ for (ALL_LIST_ELEMENTS(orig_list, node, nnode, valmask)) {
+ *target_val = valmask;
+ bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
+ bpf, bpof,
+ next_type_entry);
+ }
+}
+
static void bgp_pbr_policyroute_remove_from_zebra(struct bgp *bgp,
struct bgp_info *binfo,
struct bgp_pbr_filter *bpf,
struct bgp_pbr_or_filter *bpof)
{
- if (bpof && bpof->tcpflags) {
- struct listnode *node, *nnode;
- struct bgp_pbr_val_mask *valmask;
-
- for (ALL_LIST_ELEMENTS(bpof->tcpflags, node, nnode, valmask)) {
- bpf->tcp_flags = valmask;
- bgp_pbr_policyroute_remove_from_zebra_unit(bgp, binfo, bpf);
- XFREE(MTYPE_PBR_VALMASK, valmask);
- listnode_delete(bpof->tcpflags, node);
- }
- list_delete_all_node(bpof->tcpflags);
- bpof->tcpflags = NULL;
- } else
+ if (!bpof)
+ return bgp_pbr_policyroute_remove_from_zebra_unit(bgp,
+ binfo,
+ bpf);
+ if (bpof->tcpflags)
+ bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
+ bpf, bpof,
+ FLOWSPEC_TCP_FLAGS);
+ else if (bpof->dscp)
+ bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
+ bpf, bpof,
+ FLOWSPEC_DSCP);
+ else
bgp_pbr_policyroute_remove_from_zebra_unit(bgp, binfo, bpf);
+ /* flush bpof */
+ if (bpof->tcpflags)
+ list_delete_all_node(bpof->tcpflags);
+ if (bpof->dscp)
+ list_delete_all_node(bpof->dscp);
}
static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
@@ -1586,6 +1627,44 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
}
+static void bgp_pbr_policyroute_add_to_zebra_recursive(struct bgp *bgp,
+ struct bgp_info *binfo,
+ struct bgp_pbr_filter *bpf,
+ struct bgp_pbr_or_filter *bpof,
+ struct nexthop *nh,
+ float *rate,
+ uint8_t type_entry)
+{
+ struct listnode *node, *nnode;
+ struct bgp_pbr_val_mask *valmask;
+ uint8_t next_type_entry;
+ struct list *orig_list;
+ struct bgp_pbr_val_mask **target_val;
+
+ if (type_entry == 0)
+ return bgp_pbr_policyroute_add_to_zebra_unit(bgp, binfo, bpf,
+ nh, rate);
+ if (type_entry == FLOWSPEC_TCP_FLAGS && bpof->tcpflags) {
+ next_type_entry = FLOWSPEC_DSCP;
+ orig_list = bpof->tcpflags;
+ target_val = &bpf->tcp_flags;
+ } else if (type_entry == FLOWSPEC_DSCP && bpof->dscp) {
+ next_type_entry = 0;
+ orig_list = bpof->dscp;
+ target_val = &bpf->dscp;
+ } else {
+ return bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
+ bpf, bpof, nh, rate, 0);
+ }
+ for (ALL_LIST_ELEMENTS(orig_list, node, nnode, valmask)) {
+ *target_val = valmask;
+ bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
+ bpf, bpof,
+ nh, rate,
+ next_type_entry);
+ }
+}
+
static void bgp_pbr_policyroute_add_to_zebra(struct bgp *bgp,
struct bgp_info *binfo,
struct bgp_pbr_filter *bpf,
@@ -1593,21 +1672,27 @@ static void bgp_pbr_policyroute_add_to_zebra(struct bgp *bgp,
struct nexthop *nh,
float *rate)
{
- if (bpof && bpof->tcpflags) {
- struct listnode *node, *nnode;
- struct bgp_pbr_val_mask *valmask;
-
- for (ALL_LIST_ELEMENTS(bpof->tcpflags, node, nnode, valmask)) {
- bpf->tcp_flags = valmask;
- bgp_pbr_policyroute_add_to_zebra_unit(bgp, binfo, bpf, nh, rate);
- XFREE(MTYPE_PBR_VALMASK, valmask);
- listnode_delete(bpof->tcpflags, node);
- }
- list_delete_all_node(bpof->tcpflags);
- bpof->tcpflags = NULL;
- } else
+ if (!bpof)
return bgp_pbr_policyroute_add_to_zebra_unit(bgp, binfo,
bpf, nh, rate);
+ if (bpof->tcpflags)
+ bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
+ bpf, bpof,
+ nh, rate,
+ FLOWSPEC_TCP_FLAGS);
+ else if (bpof->dscp)
+ bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
+ bpf, bpof,
+ nh, rate,
+ FLOWSPEC_DSCP);
+ else
+ bgp_pbr_policyroute_add_to_zebra_unit(bgp, binfo, bpf,
+ nh, rate);
+ /* flush bpof */
+ if (bpof->tcpflags)
+ list_delete_all_node(bpof->tcpflags);
+ if (bpof->dscp)
+ list_delete_all_node(bpof->dscp);
}
static const struct message icmp_code_unreach_str[] = {