diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c index 9446575611..69c19fa7d8 100644 --- a/bgpd/bgp_pbr.c +++ b/bgpd/bgp_pbr.c @@ -1057,6 +1057,7 @@ uint32_t bgp_pbr_match_hash_key(const void *arg) key = jhash_1word(pbm->vrf_id, 0x4312abde); key = jhash_1word(pbm->flags, key); + key = jhash_1word(pbm->family, key); key = jhash(&pbm->pkt_len_min, 2, key); key = jhash(&pbm->pkt_len_max, 2, key); key = jhash(&pbm->tcp_flags, 2, key); @@ -1078,6 +1079,9 @@ bool bgp_pbr_match_hash_equal(const void *arg1, const void *arg2) if (r1->vrf_id != r2->vrf_id) return false; + if (r1->family != r2->family) + return false; + if (r1->type != r2->type) return false; @@ -1762,6 +1766,7 @@ static int bgp_pbr_get_remaining_entry(struct hash_bucket *bucket, void *arg) bpm_temp->pkt_len_max != bpm->pkt_len_max || bpm_temp->dscp_value != bpm->dscp_value || bpm_temp->flow_label != bpm->flow_label || + bpm_temp->family != bpm->family || bpm_temp->fragment != bpm->fragment) return HASHWALK_CONTINUE; @@ -1833,6 +1838,7 @@ static void bgp_pbr_policyroute_remove_from_zebra_unit( return; } + temp.family = bpf->family; if (bpf->src) { temp.flags |= MATCH_IP_SRC_SET; prefix_copy(&temp2.src, bpf->src); @@ -2329,6 +2335,7 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, /* then look for bpm */ memset(&temp, 0, sizeof(temp)); temp.vrf_id = bpf->vrf_id; + temp.family = bpf->family; if (bpf->src) temp.flags |= MATCH_IP_SRC_SET; if (bpf->dst) diff --git a/bgpd/bgp_pbr.h b/bgpd/bgp_pbr.h index ff333d2f10..9d6360094c 100644 --- a/bgpd/bgp_pbr.h +++ b/bgpd/bgp_pbr.h @@ -184,6 +184,7 @@ struct bgp_pbr_match { uint32_t type; uint32_t flags; + uint8_t family; uint16_t pkt_len_min; uint16_t pkt_len_max; diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index bf32d493bc..73ce990724 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -2415,7 +2415,7 @@ static void bgp_encode_pbr_ipset_match(struct stream *s, { stream_putl(s, pbim->unique); stream_putl(s, pbim->type); - + stream_putc(s, pbim->family); stream_put(s, pbim->ipset_name, ZEBRA_IPSET_NAME_SIZE); } @@ -2464,6 +2464,7 @@ static void bgp_encode_pbr_iptable_match(struct stream *s, stream_putl(s, bpa->fwmark); stream_put(s, pbm->ipset_name, ZEBRA_IPSET_NAME_SIZE); + stream_putc(s, pbm->family); stream_putw(s, pbm->pkt_len_min); stream_putw(s, pbm->pkt_len_max); stream_putw(s, pbm->tcp_flags); @@ -2471,6 +2472,7 @@ static void bgp_encode_pbr_iptable_match(struct stream *s, stream_putc(s, pbm->dscp_value); stream_putc(s, pbm->fragment); stream_putc(s, pbm->protocol); + stream_putw(s, pbm->flow_label); } /* BGP has established connection with Zebra. */ diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 2bcb3502d5..5068765d2f 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -2841,6 +2841,7 @@ static inline void zread_ipset(ZAPI_HANDLER_ARGS) zpi.vrf_id = zvrf->vrf->vrf_id; STREAM_GETL(s, zpi.unique); STREAM_GETL(s, zpi.type); + STREAM_GETC(s, zpi.family); STREAM_GET(&zpi.ipset_name, s, ZEBRA_IPSET_NAME_SIZE); if (hdr->command == ZEBRA_IPSET_CREATE) @@ -2951,6 +2952,7 @@ static inline void zread_iptable(ZAPI_HANDLER_ARGS) STREAM_GETL(s, zpi->action); STREAM_GETL(s, zpi->fwmark); STREAM_GET(&zpi->ipset_name, s, ZEBRA_IPSET_NAME_SIZE); + STREAM_GETC(s, zpi->family); STREAM_GETW(s, zpi->pkt_len_min); STREAM_GETW(s, zpi->pkt_len_max); STREAM_GETW(s, zpi->tcp_flags); @@ -2958,6 +2960,7 @@ static inline void zread_iptable(ZAPI_HANDLER_ARGS) STREAM_GETC(s, zpi->dscp_value); STREAM_GETC(s, zpi->fragment); STREAM_GETC(s, zpi->protocol); + STREAM_GETW(s, zpi->flow_label); STREAM_GETL(s, zpi->nb_interface); zebra_pbr_iptable_update_interfacelist(s, zpi); diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c index 1bc8d893bc..166689385c 100644 --- a/zebra/zebra_pbr.c +++ b/zebra/zebra_pbr.c @@ -251,6 +251,8 @@ uint32_t zebra_pbr_ipset_hash_key(const void *arg) uint32_t *pnt = (uint32_t *)&ipset->ipset_name; uint32_t key = jhash_1word(ipset->vrf_id, 0x63ab42de); + key = jhash_1word(ipset->family, key); + return jhash2(pnt, ZEBRA_IPSET_NAME_HASH_SIZE, key); } @@ -267,6 +269,8 @@ bool zebra_pbr_ipset_hash_equal(const void *arg1, const void *arg2) return false; if (r1->vrf_id != r2->vrf_id) return false; + if (r1->family != r2->family) + return false; if (strncmp(r1->ipset_name, r2->ipset_name, ZEBRA_IPSET_NAME_SIZE)) @@ -376,6 +380,8 @@ uint32_t zebra_pbr_iptable_hash_key(const void *arg) key = jhash2(pnt, ZEBRA_IPSET_NAME_HASH_SIZE, 0x63ab42de); key = jhash_1word(iptable->fwmark, key); + key = jhash_1word(iptable->family, key); + key = jhash_1word(iptable->flow_label, key); key = jhash_1word(iptable->pkt_len_min, key); key = jhash_1word(iptable->pkt_len_max, key); key = jhash_1word(iptable->tcp_flags, key); @@ -411,6 +417,10 @@ bool zebra_pbr_iptable_hash_equal(const void *arg1, const void *arg2) if (strncmp(r1->ipset_name, r2->ipset_name, ZEBRA_IPSET_NAME_SIZE)) return false; + if (r1->family != r2->family) + return false; + if (r1->flow_label != r2->flow_label) + return false; if (r1->pkt_len_min != r2->pkt_len_min) return false; if (r1->pkt_len_max != r2->pkt_len_max) @@ -876,7 +886,8 @@ static const char *zebra_pbr_prefix2str(union prefixconstptr pu, const struct prefix *p = pu.p; char buf[PREFIX2STR_BUFFER]; - if (p->family == AF_INET && p->prefixlen == IPV4_MAX_PREFIXLEN) { + if ((p->family == AF_INET && p->prefixlen == IPV4_MAX_PREFIXLEN) || + (p->family == AF_INET6 && p->prefixlen == IPV6_MAX_PREFIXLEN)) { snprintf(str, size, "%s", inet_ntop(p->family, &p->u.prefix, buf, PREFIX2STR_BUFFER)); return str; @@ -1012,8 +1023,9 @@ static int zebra_pbr_show_ipset_walkcb(struct hash_bucket *bucket, void *arg) struct vty *vty = uniqueipset->vty; struct zebra_ns *zns = uniqueipset->zns; - vty_out(vty, "IPset %s type %s\n", zpi->ipset_name, - zebra_pbr_ipset_type2str(zpi->type)); + vty_out(vty, "IPset %s type %s family %s\n", zpi->ipset_name, + zebra_pbr_ipset_type2str(zpi->type), + zpi->family == AF_INET ? "AF_INET" : "AF_INET6"); unique.vty = vty; unique.zpi = zpi; unique.zns = zns; @@ -1058,9 +1070,9 @@ void zebra_pbr_show_ipset_list(struct vty *vty, char *ipsetname) vty_out(vty, "No IPset %s found\n", ipsetname); return; } - vty_out(vty, "IPset %s type %s\n", ipsetname, - zebra_pbr_ipset_type2str(zpi->type)); - + vty_out(vty, "IPset %s type %s family %s\n", ipsetname, + zebra_pbr_ipset_type2str(zpi->type), + zpi->family == AF_INET ? "AF_INET" : "AF_INET6"); unique.vty = vty; unique.zpi = zpi; unique.zns = zns; @@ -1101,7 +1113,9 @@ static void zebra_pbr_show_iptable_unit(struct zebra_pbr_iptable *iptable, int ret; uint64_t pkts = 0, bytes = 0; - vty_out(vty, "IPtable %s action %s (%u)\n", iptable->ipset_name, + vty_out(vty, "IPtable %s family %s action %s (%u)\n", + iptable->ipset_name, + iptable->family == AF_INET ? "AF_INET" : "AF_INET6", iptable->action == ZEBRA_IPTABLES_DROP ? "drop" : "redirect", iptable->unique); if (iptable->type == IPSET_NET_PORT || @@ -1140,6 +1154,12 @@ static void zebra_pbr_show_iptable_unit(struct zebra_pbr_iptable *iptable, iptable->filter_bm & MATCH_DSCP_INVERSE_SET ? "not" : "", iptable->dscp_value); } + if (iptable->filter_bm & (MATCH_FLOW_LABEL_SET | + MATCH_FLOW_LABEL_INVERSE_SET)) { + vty_out(vty, "\t flowlabel %s %d\n", + iptable->filter_bm & MATCH_FLOW_LABEL_INVERSE_SET ? + "not" : "", iptable->flow_label); + } if (iptable->fragment) { char val_str[10]; diff --git a/zebra/zebra_pbr.h b/zebra/zebra_pbr.h index 888d2fcfa0..c84e603723 100644 --- a/zebra/zebra_pbr.h +++ b/zebra/zebra_pbr.h @@ -79,6 +79,9 @@ struct zebra_pbr_ipset { * but value is an enum ipset_type */ uint32_t type; + + uint8_t family; + char ipset_name[ZEBRA_IPSET_NAME_SIZE]; }; @@ -150,6 +153,9 @@ struct zebra_pbr_iptable { uint8_t protocol; uint32_t nb_interface; + uint16_t flow_label; + + uint8_t family; struct list *interface_name_list;