From 6cfe5d1533b2c8a5daeeb34432153f2f17e5c2e7 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Thu, 29 Nov 2018 15:14:41 +0100 Subject: [PATCH] bgpd: ip rule zebra layer adapted to handle both cases now, ip rule can be created from two differnt ways; however a single zebra API has been defined. so make it consistent by adding a parameter to the bgp zebra layer. the function will handle the rest. Signed-off-by: Philippe Guibert --- bgpd/bgp_pbr.c | 6 ++-- bgpd/bgp_zebra.c | 80 +++++++++++++++++++++++++++++++++++------------- bgpd/bgp_zebra.h | 4 ++- 3 files changed, 64 insertions(+), 26 deletions(-) diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c index 88991b676..66c20b1aa 100644 --- a/bgpd/bgp_pbr.c +++ b/bgpd/bgp_pbr.c @@ -906,7 +906,7 @@ static void bgp_pbr_action_free(void *arg) if (bpa->refcnt == 0) { if (bpa->installed && bpa->table_id != 0) { - bgp_send_pbr_rule_action(bpa, false); + bgp_send_pbr_rule_action(bpa, NULL, false); bgp_zebra_announce_default(bpa->bgp, &(bpa->nh), AFI_IP, bpa->table_id, @@ -1414,7 +1414,7 @@ static void bgp_pbr_flush_entry(struct bgp *bgp, struct bgp_pbr_action *bpa, } if (bpa->refcnt == 0) { if (bpa->installed && bpa->table_id != 0) { - bgp_send_pbr_rule_action(bpa, false); + bgp_send_pbr_rule_action(bpa, NULL, false); bgp_zebra_announce_default(bpa->bgp, &(bpa->nh), AFI_IP, bpa->table_id, @@ -2020,7 +2020,7 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, */ /* ip rule add */ if (!bpa->installed && !bpa->install_in_progress) { - bgp_send_pbr_rule_action(bpa, true); + bgp_send_pbr_rule_action(bpa, NULL, true); bgp_zebra_announce_default(bgp, nh, AFI_IP, bpa->table_id, true); } diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 3c4b21946..620b10c25 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -36,6 +36,7 @@ #include "filter.h" #include "mpls.h" #include "vxlan.h" +#include "pbr.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_route.h" @@ -2242,31 +2243,52 @@ static int iptable_notify_owner(int command, struct zclient *zclient, return 0; } +/* this function is used to forge ip rule, + * - either for iptable/ipset using fwmark id + * - or for sample ip rule command + */ static void bgp_encode_pbr_rule_action(struct stream *s, - struct bgp_pbr_action *pbra) + struct bgp_pbr_action *pbra, + struct bgp_pbr_rule *pbr) { - struct prefix any; + struct prefix pfx; stream_putl(s, 0); /* seqno unused */ stream_putl(s, 0); /* ruleno unused */ - stream_putl(s, pbra->unique); - - memset(&any, 0, sizeof(any)); - any.family = AF_INET; - stream_putc(s, any.family); - stream_putc(s, any.prefixlen); - stream_put(s, &any.u.prefix, prefix_blen(&any)); + if (pbr) + stream_putl(s, pbr->unique); + else + stream_putl(s, pbra->unique); + if (pbr && pbr->flags & MATCH_IP_SRC_SET) + memcpy(&pfx, &(pbr->src), sizeof(struct prefix)); + else { + memset(&pfx, 0, sizeof(pfx)); + pfx.family = AF_INET; + } + stream_putc(s, pfx.family); + stream_putc(s, pfx.prefixlen); + stream_put(s, &pfx.u.prefix, prefix_blen(&pfx)); stream_putw(s, 0); /* src port */ - stream_putc(s, any.family); - stream_putc(s, any.prefixlen); - stream_put(s, &any.u.prefix, prefix_blen(&any)); + if (pbr && pbr->flags & MATCH_IP_DST_SET) + memcpy(&pfx, &(pbr->dst), sizeof(struct prefix)); + else { + memset(&pfx, 0, sizeof(pfx)); + pfx.family = AF_INET; + } + stream_putc(s, pfx.family); + stream_putc(s, pfx.prefixlen); + stream_put(s, &pfx.u.prefix, prefix_blen(&pfx)); stream_putw(s, 0); /* dst port */ - stream_putl(s, pbra->fwmark); /* fwmark */ + /* if pbr present, fwmark is not used */ + if (pbr) + stream_putl(s, 0); + else + stream_putl(s, pbra->fwmark); /* fwmark */ stream_putl(s, pbra->table_id); @@ -2672,16 +2694,26 @@ int bgp_zebra_num_connects(void) return zclient_num_connects; } -void bgp_send_pbr_rule_action(struct bgp_pbr_action *pbra, bool install) +void bgp_send_pbr_rule_action(struct bgp_pbr_action *pbra, + struct bgp_pbr_rule *pbr, + bool install) { struct stream *s; - if (pbra->install_in_progress) + if (pbra->install_in_progress && !pbr) return; - if (BGP_DEBUG(zebra, ZEBRA)) - zlog_debug("%s: table %d fwmark %d %d", - __PRETTY_FUNCTION__, - pbra->table_id, pbra->fwmark, install); + if (pbr && pbr->install_in_progress) + return; + if (BGP_DEBUG(zebra, ZEBRA)) { + if (pbr) + zlog_debug("%s: table %d (ip rule) %d", + __PRETTY_FUNCTION__, + pbra->table_id, install); + else + zlog_debug("%s: table %d fwmark %d %d", + __PRETTY_FUNCTION__, + pbra->table_id, pbra->fwmark, install); + } s = zclient->obuf; stream_reset(s); @@ -2690,11 +2722,15 @@ void bgp_send_pbr_rule_action(struct bgp_pbr_action *pbra, bool install) VRF_DEFAULT); stream_putl(s, 1); /* send one pbr action */ - bgp_encode_pbr_rule_action(s, pbra); + bgp_encode_pbr_rule_action(s, pbra, pbr); stream_putw_at(s, 0, stream_get_endp(s)); - if (!zclient_send_message(zclient) && install) - pbra->install_in_progress = true; + if (!zclient_send_message(zclient) && install) { + if (!pbr) + pbra->install_in_progress = true; + else + pbr->install_in_progress = true; + } } void bgp_send_pbr_ipset_match(struct bgp_pbr_match *pbrim, bool install) diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h index e7b7d683a..c6520c43e 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h @@ -84,9 +84,11 @@ extern bool bgp_zebra_nexthop_set(union sockunion *, union sockunion *, struct bgp_pbr_action; struct bgp_pbr_match; +struct bgp_pbr_rule; struct bgp_pbr_match_entry; extern void bgp_send_pbr_rule_action(struct bgp_pbr_action *pbra, - bool install); + struct bgp_pbr_rule *pbr, + bool install); extern void bgp_send_pbr_ipset_match(struct bgp_pbr_match *pbrim, bool install); extern void bgp_send_pbr_ipset_entry_match(struct bgp_pbr_match_entry *pbrime, -- 2.39.2