diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index aa7ce6a8fb..035481aaf2 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -2712,17 +2712,20 @@ static void bgp_encode_pbr_rule_action(struct stream *s, struct bgp_pbr_action *pbra, struct bgp_pbr_rule *pbr) { - struct prefix pfx; uint8_t fam = AF_INET; - char ifname[INTERFACE_NAMSIZ]; + struct pbr_rule r; if (pbra->nh.type == NEXTHOP_TYPE_IPV6) fam = AF_INET6; - stream_putl(s, 0); /* seqno unused */ + + /* + * Convert to canonical form + */ + memset(&r, 0, sizeof(r)); + /* r.seq unused */ if (pbr) - stream_putl(s, pbr->priority); - else - stream_putl(s, 0); + r.priority = pbr->priority; + /* ruleno unused - priority change * ruleno permits distinguishing various FS PBR entries * - FS PBR entries based on ipset/iptables @@ -2730,56 +2733,37 @@ static void bgp_encode_pbr_rule_action(struct stream *s, * the latter may contain default routing information injected by FS */ if (pbr) - stream_putl(s, pbr->unique); + r.unique = pbr->unique; else - stream_putl(s, pbra->unique); + r.unique = pbra->unique; - stream_putl(s, 0); /* filter_bm placeholder */ - stream_putc(s, 0); /* ip protocol being used */ - if (pbr && pbr->flags & MATCH_IP_SRC_SET) - memcpy(&pfx, &(pbr->src), sizeof(struct prefix)); - else { - memset(&pfx, 0, sizeof(pfx)); - pfx.family = fam; + /* filter */ + + if (pbr && pbr->flags & MATCH_IP_SRC_SET) { + SET_FLAG(r.filter.filter_bm, PBR_FILTER_SRC_IP); + r.filter.src_ip = pbr->src; + } else { + /* ??? */ + r.filter.src_ip.family = fam; } - 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 */ - - if (pbr && pbr->flags & MATCH_IP_DST_SET) - memcpy(&pfx, &(pbr->dst), sizeof(struct prefix)); - else { - memset(&pfx, 0, sizeof(pfx)); - pfx.family = fam; + if (pbr && pbr->flags & MATCH_IP_DST_SET) { + SET_FLAG(r.filter.filter_bm, PBR_FILTER_DST_IP); + r.filter.dst_ip = pbr->dst; + } else { + /* ??? */ + r.filter.dst_ip.family = fam; + } + /* src_port, dst_port, pcp, dsfield not used */ + if (!pbr) { + SET_FLAG(r.filter.filter_bm, PBR_FILTER_FWMARK); + r.filter.fwmark = pbra->fwmark; } - 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 */ + SET_FLAG(r.action.flags, PBR_ACTION_TABLE); /* always valid */ + r.action.table = pbra->table_id; - stream_putc(s, 0); /* filter dsfield */ - /* if pbr present, fwmark is not used */ - if (pbr) - stream_putl(s, 0); - else - stream_putl(s, pbra->fwmark); /* filter fwmark */ - - stream_putc(s, 0); /* pcp filter */ - stream_putw(s, 0); /* pcp action */ - stream_putw(s, 0); /* vlan_id filter */ - stream_putw(s, 0); /* vlan_flags filter */ - stream_putw(s, 0); /* vlan_id action */ - stream_putw(s, 0); /* vlan_flags action */ - stream_putl(s, 0); /* queue id action */ - - stream_putl(s, pbra->table_id); /* table action */ - - memset(ifname, 0, sizeof(ifname)); - stream_put(s, ifname, INTERFACE_NAMSIZ); /* ifname unused */ + zapi_pbr_rule_encode(s, &r); } static void bgp_encode_pbr_ipset_match(struct stream *s, @@ -3545,11 +3529,9 @@ void bgp_send_pbr_rule_action(struct bgp_pbr_action *pbra, zclient_create_header(s, install ? ZEBRA_RULE_ADD : ZEBRA_RULE_DELETE, VRF_DEFAULT); - stream_putl(s, 1); /* send one pbr action */ bgp_encode_pbr_rule_action(s, pbra, pbr); - stream_putw_at(s, 0, stream_get_endp(s)); if ((zclient_send_message(zclient) != ZCLIENT_SEND_FAILURE) && install) { if (!pbr) diff --git a/lib/pbr.h b/lib/pbr.h index f4b6633812..1a3d562ed9 100644 --- a/lib/pbr.h +++ b/lib/pbr.h @@ -85,14 +85,23 @@ struct pbr_filter { * the user criteria may directly point to a table too. */ struct pbr_action { + uint32_t flags; + +#define PBR_ACTION_TABLE (1 << 0) +#define PBR_ACTION_QUEUE_ID (1 << 1) +#define PBR_ACTION_PCP (1 << 2) +#define PBR_ACTION_VLAN_ID (1 << 3) +#define PBR_ACTION_VLAN_FLAGS (1 << 4) + + uint32_t table; + uint32_t queue_id; + /* VLAN */ uint8_t pcp; uint16_t vlan_id; uint16_t vlan_flags; - uint32_t queue_id; - uint32_t table; }; /* @@ -146,8 +155,8 @@ struct pbr_rule { #define MATCH_FLOW_LABEL_SET (1 << 12) #define MATCH_FLOW_LABEL_INVERSE_SET (1 << 13) -extern int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s, - struct pbr_rule *zrule); +extern int zapi_pbr_rule_encode(struct stream *s, struct pbr_rule *r); +extern bool zapi_pbr_rule_decode(struct stream *s, struct pbr_rule *r); #ifdef __cplusplus } diff --git a/lib/zclient.c b/lib/zclient.c index 929a18a953..c6d06ee6d6 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1611,30 +1611,105 @@ static void zapi_encode_prefix(struct stream *s, struct prefix *p, stream_put(s, &p->u.prefix, prefix_blen(p)); } -int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s, struct pbr_rule *zrule) +static bool zapi_decode_prefix(struct stream *s, struct prefix *p) { - stream_reset(s); - zclient_create_header(s, cmd, zrule->vrf_id); + STREAM_GETC(s, p->family); + STREAM_GETC(s, p->prefixlen); + STREAM_GET(&(p->u.prefix), s, prefix_blen(p)); + return true; +stream_failure: + return false; +} + +/* + * Encode filter subsection of pbr_rule + */ +static void zapi_pbr_rule_filter_encode(struct stream *s, struct pbr_filter *f) +{ + assert(f->src_ip.family == f->dst_ip.family); + assert((AF_INET == f->src_ip.family) || (AF_INET6 == f->src_ip.family)); + + stream_putl(s, f->filter_bm); + stream_putc(s, f->ip_proto); + + /* addresses */ + zapi_encode_prefix(s, &f->src_ip, f->src_ip.family); + zapi_encode_prefix(s, &f->dst_ip, f->dst_ip.family); + + /* port numbers */ + stream_putw(s, f->src_port); + stream_putw(s, f->dst_port); + + /* vlan */ + stream_putc(s, f->pcp); + stream_putw(s, f->vlan_id); + stream_putw(s, f->vlan_flags); + + stream_putc(s, f->dsfield); + stream_putl(s, f->fwmark); +} + +static bool zapi_pbr_rule_filter_decode(struct stream *s, struct pbr_filter *f) +{ + STREAM_GETL(s, f->filter_bm); + STREAM_GETC(s, f->ip_proto); + if (!zapi_decode_prefix(s, &(f->src_ip))) + goto stream_failure; + if (!zapi_decode_prefix(s, &(f->dst_ip))) + goto stream_failure; + STREAM_GETW(s, f->src_port); + STREAM_GETW(s, f->dst_port); + STREAM_GETC(s, f->pcp); + STREAM_GETW(s, f->vlan_id); + STREAM_GETW(s, f->vlan_flags); + STREAM_GETC(s, f->dsfield); + STREAM_GETL(s, f->fwmark); + return true; + +stream_failure: + return false; +} + +static void zapi_pbr_rule_action_encode(struct stream *s, struct pbr_action *a) +{ + stream_putl(s, a->flags); + stream_putl(s, a->table); + stream_putl(s, a->queue_id); + stream_putc(s, a->pcp); + stream_putw(s, a->vlan_id); + stream_putw(s, a->vlan_flags); +} + +static bool zapi_pbr_rule_action_decode(struct stream *s, struct pbr_action *a) +{ + STREAM_GETL(s, a->flags); + STREAM_GETL(s, a->table); + STREAM_GETL(s, a->queue_id); + STREAM_GETC(s, a->pcp); + STREAM_GETW(s, a->vlan_id); + STREAM_GETW(s, a->vlan_flags); + return true; + +stream_failure: + return false; +} + +int zapi_pbr_rule_encode(struct stream *s, struct pbr_rule *r) +{ /* - * We are sending one item at a time at the moment + * PBR record count is always 1 */ stream_putl(s, 1); - stream_putl(s, zrule->seq); - stream_putl(s, zrule->priority); - stream_putl(s, zrule->unique); + stream_putl(s, r->seq); + stream_putl(s, r->priority); + stream_putl(s, r->unique); - zapi_encode_prefix(s, &(zrule->filter.src_ip), - zrule->filter.src_ip.family); - stream_putw(s, zrule->filter.src_port); /* src port */ - zapi_encode_prefix(s, &(zrule->filter.dst_ip), - zrule->filter.src_ip.family); - stream_putw(s, zrule->filter.dst_port); /* dst port */ - stream_putw(s, zrule->filter.fwmark); /* fwmark */ + zapi_pbr_rule_filter_encode(s, &(r->filter)); + zapi_pbr_rule_action_encode(s, &(r->action)); - stream_putl(s, zrule->action.table); - stream_put(s, zrule->ifname, INTERFACE_NAMSIZ); + stream_put(s, r->ifname, INTERFACE_NAMSIZ); /* Put length at the first point of the stream. */ stream_putw_at(s, 0, stream_get_endp(s)); @@ -1642,6 +1717,28 @@ int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s, struct pbr_rule *zrule) return 0; } +bool zapi_pbr_rule_decode(struct stream *s, struct pbr_rule *r) +{ + /* NB caller has already read 4-byte rule count */ + + memset(r, 0, sizeof(*r)); + + STREAM_GETL(s, r->seq); + STREAM_GETL(s, r->priority); + STREAM_GETL(s, r->unique); + + if (!zapi_pbr_rule_filter_decode(s, &(r->filter))) + goto stream_failure; + if (!zapi_pbr_rule_action_decode(s, &(r->action))) + goto stream_failure; + + STREAM_GET(r->ifname, s, INTERFACE_NAMSIZ); + return true; + +stream_failure: + return false; +} + int zapi_tc_qdisc_encode(uint8_t cmd, struct stream *s, struct tc_qdisc *qdisc) { stream_reset(s); diff --git a/pbrd/pbr_zebra.c b/pbrd/pbr_zebra.c index 28d89b0b5c..f4bf287c59 100644 --- a/pbrd/pbr_zebra.c +++ b/pbrd/pbr_zebra.c @@ -483,27 +483,9 @@ void pbr_send_rnh(struct nexthop *nhop, bool reg) } } -static void pbr_encode_pbr_map_sequence_prefix(struct stream *s, - struct prefix *p, - unsigned char family) -{ - struct prefix any; - if (!p) { - memset(&any, 0, sizeof(any)); - any.family = family; - p = &any; - } - - stream_putc(s, p->family); - stream_putc(s, p->prefixlen); - 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) +static uint32_t pbr_map_sequence_vrf(const struct pbr_map_sequence *pbrms, + const struct interface *ifp) { struct pbr_vrf *pbr_vrf; @@ -514,66 +496,130 @@ pbr_encode_pbr_map_sequence_vrf(struct stream *s, if (!pbr_vrf) { DEBUGD(&pbr_dbg_zebra, "%s: VRF not found", __func__); - return; + return 0; } - stream_putl(s, pbr_vrf->vrf->data.l.table_id); + return pbr_vrf->vrf->data.l.table_id; + } +/* + * 230716 gpz note: it would be worthwhile for pbrd to represent + * its rules internally using the lib/pbr.h structures to help + * move toward a more common structure across pbrd, bgpd, and zebra. + */ static bool pbr_encode_pbr_map_sequence(struct stream *s, struct pbr_map_sequence *pbrms, struct interface *ifp) { - unsigned char family; + struct pbr_rule r; + uint8_t family; + + /* + * There seems to be some effort in pbr_vty.c to keep the three + * copies of "family" equal. Not sure if the reason goes beyond + * ensuring consistency in ZAPI encoding. In any case, it might + * be handled better as an internal matter for the encoder (TBD). + */ family = AF_INET; if (pbrms->family) family = pbrms->family; - stream_putl(s, pbrms->seqno); - stream_putl(s, pbrms->ruleno); - stream_putl(s, pbrms->unique); + if (pbrms->src) + assert(family == pbrms->src->family); + if (pbrms->dst) + assert(family == pbrms->dst->family); - stream_putl(s, pbrms->filter_bm); + /* + * Convert struct pbr_map_sequence to canonical form + */ + memset(&r, 0, sizeof(r)); + r.seq = pbrms->seqno; + r.priority = pbrms->ruleno; + r.unique = pbrms->unique; - stream_putc(s, pbrms->ip_proto); /* The ip_proto */ - pbr_encode_pbr_map_sequence_prefix(s, pbrms->src, family); - stream_putw(s, pbrms->src_prt); - pbr_encode_pbr_map_sequence_prefix(s, pbrms->dst, family); - stream_putw(s, pbrms->dst_prt); - stream_putc(s, pbrms->dsfield); - stream_putl(s, pbrms->mark); - /* PCP */ - if (CHECK_FLAG(pbrms->filter_bm, PBR_FILTER_PCP)) - stream_putc(s, pbrms->match_pcp); + /* filter */ + r.filter.filter_bm = pbrms->filter_bm; + if (pbrms->src) + r.filter.src_ip = *pbrms->src; else - stream_putc(s, 0); - stream_putw(s, pbrms->action_pcp); - /* VLAN */ - stream_putw(s, pbrms->match_vlan_id); - stream_putw(s, pbrms->match_vlan_flags); + r.filter.src_ip.family = family; + if (pbrms->dst) + r.filter.dst_ip = *pbrms->dst; + else + r.filter.dst_ip.family = family; + r.filter.src_port = pbrms->src_prt; + r.filter.dst_port = pbrms->dst_prt; + r.filter.pcp = pbrms->match_pcp; + r.filter.vlan_id = pbrms->match_vlan_id; + r.filter.vlan_flags = pbrms->match_vlan_flags; + r.filter.dsfield = pbrms->dsfield; + r.filter.fwmark = pbrms->mark; + r.filter.ip_proto = pbrms->ip_proto; - stream_putw(s, pbrms->action_vlan_id); - stream_putw(s, pbrms->action_vlan_flags); - stream_putl(s, pbrms->action_queue_id); + /* + * Fix up filter flags for now, since PBRD doesn't maintain + * them yet (aside from PBR_FILTER_PCP) + */ + if (!is_default_prefix(&r.filter.src_ip)) + SET_FLAG(r.filter.filter_bm, PBR_FILTER_SRC_IP); + if (!is_default_prefix(&r.filter.dst_ip)) + SET_FLAG(r.filter.filter_bm, PBR_FILTER_DST_IP); + if (r.filter.src_port) + SET_FLAG(r.filter.filter_bm, PBR_FILTER_SRC_PORT); + if (r.filter.dst_port) + SET_FLAG(r.filter.filter_bm, PBR_FILTER_DST_PORT); + if (r.filter.vlan_id) + SET_FLAG(r.filter.filter_bm, PBR_FILTER_VLAN_ID); + if (r.filter.vlan_flags) + SET_FLAG(r.filter.filter_bm, PBR_FILTER_VLAN_FLAGS); + if (r.filter.dsfield) + SET_FLAG(r.filter.filter_bm, PBR_FILTER_DSFIELD); + if (r.filter.fwmark) + SET_FLAG(r.filter.filter_bm, PBR_FILTER_FWMARK); + if (r.filter.ip_proto) + SET_FLAG(r.filter.filter_bm, PBR_FILTER_IP_PROTOCOL); - /* if the user does not use the command "set vrf name |unchanged" + /* actions */ + + /* + * PBR should maintain its own set of action flags that we + * can copy here instead of trying to infer from magic values. + */ + SET_FLAG(r.action.flags, PBR_ACTION_TABLE); /* always valid */ + if (PBR_MAP_UNDEFINED_QUEUE_ID != pbrms->action_queue_id) + SET_FLAG(r.action.flags, PBR_ACTION_QUEUE_ID); + if (0 != pbrms->action_pcp) + SET_FLAG(r.action.flags, PBR_ACTION_PCP); + if (0 != pbrms->action_vlan_id) + SET_FLAG(r.action.flags, PBR_ACTION_VLAN_ID); + if (0 != pbrms->action_vlan_flags) + SET_FLAG(r.action.flags, PBR_ACTION_VLAN_FLAGS); + + /* + * if the user does not use the command "set vrf name unchanged" * then pbr_encode_pbr_map_sequence_vrf will not be called */ - - /* these statement get a table id */ if (pbrms->vrf_unchanged || pbrms->vrf_lookup) - pbr_encode_pbr_map_sequence_vrf(s, pbrms, ifp); + r.action.table = pbr_map_sequence_vrf(pbrms, ifp); else if (pbrms->nhgrp_name) - stream_putl(s, pbr_nht_get_table(pbrms->nhgrp_name)); + r.action.table = pbr_nht_get_table(pbrms->nhgrp_name); else if (pbrms->nhg) - stream_putl(s, pbr_nht_get_table(pbrms->internal_nhg_name)); + r.action.table = pbr_nht_get_table(pbrms->internal_nhg_name); else { /* Not valid for install without table */ return false; } - stream_put(s, ifp->name, INTERFACE_NAMSIZ); + r.action.queue_id = pbrms->action_queue_id; + r.action.pcp = pbrms->action_pcp; + r.action.vlan_id = pbrms->action_vlan_id; + r.action.vlan_flags = pbrms->action_vlan_flags; + + strlcpy(r.ifname, ifp->name, sizeof(r.ifname)); + + zapi_pbr_rule_encode(s, &r); return true; } @@ -607,11 +653,6 @@ bool pbr_send_pbr_map(struct pbr_map_sequence *pbrms, install ? ZEBRA_RULE_ADD : ZEBRA_RULE_DELETE, VRF_DEFAULT); - /* - * We are sending one item at a time at the moment - */ - stream_putl(s, 1); - DEBUGD(&pbr_dbg_zebra, "%s: %s %s seq %u %d %s %u", __func__, install ? "Installing" : "Deleting", pbrm->name, pbrms->seqno, install, pmi->ifp->name, pmi->delete); diff --git a/tests/topotests/pbr_topo1/test_pbr_topo1.py b/tests/topotests/pbr_topo1/test_pbr_topo1.py index 699e4489a3..ad096fa14e 100644 --- a/tests/topotests/pbr_topo1/test_pbr_topo1.py +++ b/tests/topotests/pbr_topo1/test_pbr_topo1.py @@ -181,8 +181,10 @@ def test_pbr_data(): # # -# tm: must-match pattern -# tN: must Not match pattern +# c: command +# cDN: omit default destination IP address (special case) +# tm: must-match pattern +# tN: must Not match pattern # # Note we are searching amid a bunch of other rules, so these elements # should be unique. @@ -199,6 +201,27 @@ ftest = [ {"c": "match vlan untagged", "tm": r"VLAN Flags Match: untagged$"}, {"c": "match vlan untagged-or-zero", "tm": r"VLAN Flags Match: untagged-or-zero$"}, {"c": "no match vlan tagged", "tN": r"VLAN Flags Match:"}, + + {"c": "match src-ip 37.49.22.0/24", "tm": r"SRC IP Match: 37.49.22.0/24$"}, + {"c": "no match src-ip 37.49.22.0/24", "tN": r"SRC IP Match: 37.49.22.0/24$"}, + + {"c": "match dst-ip 38.41.29.0/25", "cDN": "foo", "tm": r"DST IP Match: 38.41.29.0/25$"}, + {"c": "no match dst-ip 38.41.29.0/25", "tN": r"DST IP Match: 38.41.29.0/25$"}, + + {"c": "match src-port 117", "tm": r"SRC Port Match: 117$"}, + {"c": "no match src-port 117", "tN": r"SRC Port Match: 117$"}, + + {"c": "match dst-port 119", "tm": r"DST Port Match: 119$"}, + {"c": "no match dst-port 119", "tN": r"DST Port Match: 119$"}, + + {"c": "match dscp cs3", "tm": r"DSCP Match: 24$"}, + {"c": "no match dscp cs3", "tN": r"DSCP Match: 24$"}, + + {"c": "match ecn 2", "tm": r"ECN Match: 2$"}, + {"c": "no match ecn 2", "tN": r"ECN Match: 2$"}, + + {"c": "match mark 337", "tm": r"MARK Match: 337$"}, + {"c": "no match mark 337", "tN": r"MARK Match: 337$"}, ] @@ -233,6 +256,9 @@ def test_pbr_fields(): logger.info("Verifying PBR rule fields") + # uncomment for manual interaction + # tgen.cli() + tag = "field" router_list = tgen.routers().values() @@ -240,8 +266,12 @@ def test_pbr_fields(): for t in ftest: # send field-setting command # always have a match dst-ip to satisfy rule non-empty check - vcmd = "c t\npbr-map ASAKUSA seq 100\n{}\nmatch dst-ip 9.9.9.9/32\nset nexthop-group A\nend\nend".format( - t["c"] + if "cDN" in t: + match_dstip = "" + else: + match_dstip = "match dst-ip 9.9.9.9/32\n" + vcmd = "c t\npbr-map ASAKUSA seq 100\n{}\n{}set nexthop-group A\nend\nend".format( + t["c"], match_dstip ) router.vtysh_multicmd(vcmd) diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 928cb3f9b7..a136fcf8ae 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -3184,7 +3184,6 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS) struct zebra_pbr_rule zpr; struct stream *s; uint32_t total, i; - char ifname[INTERFACE_NAMSIZ + 1] = {}; s = msg; STREAM_GETL(s, total); @@ -3194,68 +3193,11 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS) zpr.sock = client->sock; zpr.rule.vrf_id = hdr->vrf_id; - STREAM_GETL(s, zpr.rule.seq); - STREAM_GETL(s, zpr.rule.priority); - STREAM_GETL(s, zpr.rule.unique); - STREAM_GETL(s, zpr.rule.filter.filter_bm); + if (!zapi_pbr_rule_decode(s, &zpr.rule)) + goto stream_failure; - STREAM_GETC(s, zpr.rule.filter.ip_proto); - STREAM_GETC(s, zpr.rule.filter.src_ip.family); - STREAM_GETC(s, zpr.rule.filter.src_ip.prefixlen); - STREAM_GET(&zpr.rule.filter.src_ip.u.prefix, s, - prefix_blen(&zpr.rule.filter.src_ip)); - STREAM_GETW(s, zpr.rule.filter.src_port); - STREAM_GETC(s, zpr.rule.filter.dst_ip.family); - STREAM_GETC(s, zpr.rule.filter.dst_ip.prefixlen); - STREAM_GET(&zpr.rule.filter.dst_ip.u.prefix, s, - prefix_blen(&zpr.rule.filter.dst_ip)); - STREAM_GETW(s, zpr.rule.filter.dst_port); - STREAM_GETC(s, zpr.rule.filter.dsfield); - STREAM_GETL(s, zpr.rule.filter.fwmark); - - STREAM_GETC(s, zpr.rule.filter.pcp); - STREAM_GETW(s, zpr.rule.action.pcp); - STREAM_GETW(s, zpr.rule.filter.vlan_id); - STREAM_GETW(s, zpr.rule.filter.vlan_flags); - STREAM_GETW(s, zpr.rule.action.vlan_id); - STREAM_GETW(s, zpr.rule.action.vlan_flags); - STREAM_GETL(s, zpr.rule.action.queue_id); - - STREAM_GETL(s, zpr.rule.action.table); - STREAM_GET(ifname, s, INTERFACE_NAMSIZ); - - strlcpy(zpr.ifname, ifname, sizeof(zpr.ifname)); - strlcpy(zpr.rule.ifname, ifname, sizeof(zpr.rule.ifname)); - - if (!is_default_prefix(&zpr.rule.filter.src_ip)) - zpr.rule.filter.filter_bm |= PBR_FILTER_SRC_IP; - - if (!is_default_prefix(&zpr.rule.filter.dst_ip)) - zpr.rule.filter.filter_bm |= PBR_FILTER_DST_IP; - - if (zpr.rule.filter.src_port) - zpr.rule.filter.filter_bm |= PBR_FILTER_SRC_PORT; - - if (zpr.rule.filter.dst_port) - zpr.rule.filter.filter_bm |= PBR_FILTER_DST_PORT; - - if (zpr.rule.filter.dsfield) - zpr.rule.filter.filter_bm |= PBR_FILTER_DSFIELD; - - if (zpr.rule.filter.ip_proto) - zpr.rule.filter.filter_bm |= PBR_FILTER_IP_PROTOCOL; - - if (zpr.rule.filter.fwmark) - zpr.rule.filter.filter_bm |= PBR_FILTER_FWMARK; - - /* NB PBR_FILTER_PCP should already be set by sender */ - - if (zpr.rule.filter.vlan_flags) - zpr.rule.filter.filter_bm |= PBR_FILTER_VLAN_FLAGS; - - if (zpr.rule.filter.vlan_id) - zpr.rule.filter.filter_bm |= PBR_FILTER_VLAN_ID; + strlcpy(zpr.ifname, zpr.rule.ifname, sizeof(zpr.ifname)); if (!(zpr.rule.filter.src_ip.family == AF_INET || zpr.rule.filter.src_ip.family == AF_INET6)) {