[ovs-dev] [PATCH 4/4] flow: Enable matching on new field 'pkt_mark'.
Andy Zhou
azhou at nicira.com
Tue Aug 13 20:48:25 UTC 2013
All 4 patches look good to me.
Acked-by: Andy Zhou <azhou at nicira.com>
On Tue, Aug 6, 2013 at 12:57 PM, Jesse Gross <jesse at nicira.com> wrote:
> The Linux kernel datapath enables matching and setting the skb mark
> but this functionality is currently used only internally by
> ovs-vswitchd. This exposes it through NXM to enable external
> controllers to interact with other kernel subsystems. Although this
> is simply exporting the skb mark, the intention is that this is a
> platform independent mechanism to access some system metadata and
> therefore may have different implementations on various systems.
>
> Bug #17855
>
> Signed-off-by: Jesse Gross <jesse at nicira.com>
> ---
> NEWS | 3 +++
> include/openflow/nicira-ext.h | 17 +++++++++++++++++
> lib/flow.c | 1 +
> lib/flow.h | 1 +
> lib/match.c | 21 +++++++++++++++++----
> lib/match.h | 1 +
> lib/meta-flow.c | 14 +++++++++-----
> lib/nx-match.c | 4 ++++
> lib/ofp-print.c | 4 ++++
> lib/ofp-util.c | 15 +++++++++++++--
> tests/ofproto.at | 4 ++--
> tests/ovs-ofctl.at | 8 +++++---
> utilities/ovs-ofctl.8.in | 7 +++++++
> 13 files changed, 84 insertions(+), 16 deletions(-)
>
> diff --git a/NEWS b/NEWS
> index f9953ab..0165eff 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -10,6 +10,9 @@ v1.12.0 - xx xxx xxxx
> * New support for matching outer source and destination IP address
> of tunneled packets, for tunnel ports configured with the newly
> added "remote_ip=flow" and "local_ip=flow" options.
> + * Support for matching on metadata 'pkt_mark' for interacting with
> + other system components. On Linux this corresponds to the skb
> + mark.
> - The Interface table in the database has a new "ifindex" column to
> report the interface's OS-assigned ifindex.
> - New "check-oftest" Makefile target for running OFTest against Open
> diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h
> index 6319f4e..de5ff6a 100644
> --- a/include/openflow/nicira-ext.h
> +++ b/include/openflow/nicira-ext.h
> @@ -477,6 +477,7 @@ OFP_ASSERT(sizeof(struct nx_action_pop_queue) == 16);
> * - NXM_NX_ND_SLL
> * - NXM_NX_ND_TLL
> * - NXM_NX_REG(idx) for idx in the switch's accepted range.
> + * - NXM_NX_PKT_MARK
> * - NXM_NX_TUN_IPV4_SRC
> * - NXM_NX_TUN_IPV4_DST
> *
> @@ -498,6 +499,8 @@ OFP_ASSERT(sizeof(struct nx_action_pop_queue) == 16);
> *
> * - NXM_NX_REG(idx) for idx in the switch's accepted range.
> *
> + * - NXM_NX_PKT_MARK
> + *
> * - NXM_OF_VLAN_TCI. Modifying this field's value has side effects on
> the
> * packet's 802.1Q header. Setting a value with CFI=0 removes the
> 802.1Q
> * header (if any), ignoring the other bits. Setting a value with
> CFI=1
> @@ -1766,6 +1769,20 @@ OFP_ASSERT(sizeof(struct nx_action_output_reg) ==
> 24);
> #define NXM_NX_TUN_IPV4_DST NXM_HEADER (0x0001, 32, 4)
> #define NXM_NX_TUN_IPV4_DST_W NXM_HEADER_W(0x0001, 32, 4)
>
> +/* Metadata marked onto the packet in a system-dependent manner.
> + *
> + * The packet mark may be used to carry contextual information
> + * to other parts of the system outside of Open vSwitch. As a
> + * result, the semantics depend on system in use.
> + *
> + * Prereqs: None.
> + *
> + * Format: 32-bit integer in network byte order.
> + *
> + * Masking: Fully maskable. */
> +#define NXM_NX_PKT_MARK NXM_HEADER (0x0001, 33, 4)
> +#define NXM_NX_PKT_MARK_W NXM_HEADER_W(0x0001, 33, 4)
> +
> /* ## --------------------- ## */
> /* ## Requests and replies. ## */
> /* ## --------------------- ## */
> diff --git a/lib/flow.c b/lib/flow.c
> index a60965e..3e29aa1 100644
> --- a/lib/flow.c
> +++ b/lib/flow.c
> @@ -500,6 +500,7 @@ flow_get_metadata(const struct flow *flow, struct
> flow_metadata *fmd)
> fmd->tun_dst = flow->tunnel.ip_dst;
> fmd->metadata = flow->metadata;
> memcpy(fmd->regs, flow->regs, sizeof fmd->regs);
> + fmd->pkt_mark = flow->pkt_mark;
> fmd->in_port = flow->in_port.ofp_port;
> }
>
> diff --git a/lib/flow.h b/lib/flow.h
> index 4c5fc03..8164d9c 100644
> --- a/lib/flow.h
> +++ b/lib/flow.h
> @@ -128,6 +128,7 @@ struct flow_metadata {
> ovs_be32 tun_dst; /* Tunnel outer IPv4 dst addr */
> ovs_be64 metadata; /* OpenFlow 1.1+ metadata field. */
> uint32_t regs[FLOW_N_REGS]; /* Registers. */
> + uint32_t pkt_mark; /* Packet mark. */
> ofp_port_t in_port; /* OpenFlow port or zero. */
> };
>
> diff --git a/lib/match.c b/lib/match.c
> index db1553b..e97b0b1 100644
> --- a/lib/match.c
> +++ b/lib/match.c
> @@ -138,7 +138,6 @@ match_init_exact(struct match *match, const struct
> flow *flow)
> {
> match->flow = *flow;
> match->flow.skb_priority = 0;
> - match->flow.pkt_mark = 0;
> flow_wildcards_init_exact(&match->wc);
> }
>
> @@ -288,8 +287,14 @@ match_set_skb_priority(struct match *match, uint32_t
> skb_priority)
> void
> match_set_pkt_mark(struct match *match, uint32_t pkt_mark)
> {
> - match->wc.masks.pkt_mark = UINT32_MAX;
> - match->flow.pkt_mark = pkt_mark;
> + match_set_pkt_mark_masked(match, pkt_mark, UINT32_MAX);
> +}
> +
> +void
> +match_set_pkt_mark_masked(struct match *match, uint32_t pkt_mark,
> uint32_t mask)
> +{
> + match->flow.pkt_mark = pkt_mark & mask;
> + match->wc.masks.pkt_mark = mask;
> }
>
> void
> @@ -836,8 +841,16 @@ match_format(const struct match *match, struct ds *s,
> unsigned int priority)
> ds_put_format(s, "priority=%u,", priority);
> }
>
> - if (wc->masks.pkt_mark) {
> + switch (wc->masks.pkt_mark) {
> + case 0:
> + break;
> + case UINT32_MAX:
> ds_put_format(s, "pkt_mark=%#"PRIx32",", f->pkt_mark);
> + break;
> + default:
> + ds_put_format(s, "pkt_mark=%#"PRIx32"/%#"PRIx32",",
> + f->pkt_mark, wc->masks.pkt_mark);
> + break;
> }
>
> if (wc->masks.skb_priority) {
> diff --git a/lib/match.h b/lib/match.h
> index f6b9868..5788721 100644
> --- a/lib/match.h
> +++ b/lib/match.h
> @@ -62,6 +62,7 @@ void match_set_tun_flags(struct match *match, uint16_t
> flags);
> void match_set_tun_flags_masked(struct match *match, uint16_t flags,
> uint16_t mask);
> void match_set_in_port(struct match *, ofp_port_t ofp_port);
> void match_set_pkt_mark(struct match *, uint32_t pkt_mark);
> +void match_set_pkt_mark_masked(struct match *, uint32_t pkt_mark,
> uint32_t mask);
> void match_set_skb_priority(struct match *, uint32_t skb_priority);
> void match_set_dl_type(struct match *, ovs_be16);
> void match_set_dl_src(struct match *, const uint8_t[6]);
> diff --git a/lib/meta-flow.c b/lib/meta-flow.c
> index 92849eb..ce061a3 100644
> --- a/lib/meta-flow.c
> +++ b/lib/meta-flow.c
> @@ -139,12 +139,12 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
> }, {
> MFF_PKT_MARK, "pkt_mark", NULL,
> MF_FIELD_SIZES(be32),
> - MFM_NONE,
> + MFM_FULLY,
> MFS_HEXADECIMAL,
> MFP_NONE,
> - false,
> - 0, NULL,
> - 0, NULL,
> + true,
> + NXM_NX_PKT_MARK, "NXM_NX_PKT_MARK",
> + NXM_NX_PKT_MARK, "NXM_NX_PKT_MARK",
> },
>
> #define REGISTER(IDX) \
> @@ -1780,7 +1780,6 @@ mf_set(const struct mf_field *mf,
> switch (mf->id) {
> case MFF_IN_PORT:
> case MFF_IN_PORT_OXM:
> - case MFF_PKT_MARK:
> case MFF_SKB_PRIORITY:
> case MFF_ETH_TYPE:
> case MFF_DL_VLAN:
> @@ -1829,6 +1828,11 @@ mf_set(const struct mf_field *mf,
> ntohl(value->be32), ntohl(mask->be32));
> break;
>
> + case MFF_PKT_MARK:
> + match_set_pkt_mark_masked(match, ntohl(value->be32),
> + ntohl(mask->be32));
> + break;
> +
> case MFF_ETH_DST:
> match_set_dl_dst_masked(match, value->mac, mask->mac);
> break;
> diff --git a/lib/nx-match.c b/lib/nx-match.c
> index 940dd9a..09f7f54 100644
> --- a/lib/nx-match.c
> +++ b/lib/nx-match.c
> @@ -693,6 +693,10 @@ nx_put_raw(struct ofpbuf *b, bool oxm, const struct
> match *match,
> htonl(flow->regs[i]), htonl(match->wc.masks.regs[i]));
> }
>
> + /* Mark. */
> + nxm_put_32m(b, NXM_NX_PKT_MARK, htonl(flow->pkt_mark),
> + htonl(match->wc.masks.pkt_mark));
> +
> /* OpenFlow 1.1+ Metadata. */
> nxm_put_64m(b, OXM_OF_METADATA, flow->metadata,
> match->wc.masks.metadata);
>
> diff --git a/lib/ofp-print.c b/lib/ofp-print.c
> index 1a4dd9c..21989a9 100644
> --- a/lib/ofp-print.c
> +++ b/lib/ofp-print.c
> @@ -130,6 +130,10 @@ ofp_print_packet_in(struct ds *string, const struct
> ofp_header *oh,
> }
> }
>
> + if (pin.fmd.pkt_mark != 0) {
> + ds_put_format(string, " pkt_mark=0x%"PRIx32, pin.fmd.pkt_mark);
> + }
> +
> ds_put_format(string, " (via %s)",
> ofputil_packet_in_reason_to_string(pin.reason,
> reasonbuf,
> sizeof reasonbuf));
> diff --git a/lib/ofp-util.c b/lib/ofp-util.c
> index 6ae67a9..45ff0a1 100644
> --- a/lib/ofp-util.c
> +++ b/lib/ofp-util.c
> @@ -1134,11 +1134,17 @@ ofputil_usable_protocols(const struct match *match)
> return OFPUTIL_P_NONE;
> }
>
> - /* pkt_mark and skb_priority can't be sent in a flow_mod */
> - if (wc->masks.pkt_mark || wc->masks.skb_priority) {
> + /* skb_priority can't be sent in a flow_mod */
> + if (wc->masks.skb_priority) {
> return OFPUTIL_P_NONE;
> }
>
> + /* NXM and OXM support pkt_mark */
> + if (wc->masks.pkt_mark) {
> + return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
> + | OFPUTIL_P_OF13_OXM;
> + }
> +
> /* NXM, OXM, and OF1.1 support bitwise matching on ethernet
> addresses. */
> if (!eth_mask_is_exact(wc->masks.dl_src)
> && !eth_addr_is_zero(wc->masks.dl_src)) {
> @@ -2917,6 +2923,7 @@ ofputil_decode_packet_in_finish(struct
> ofputil_packet_in *pin,
> pin->fmd.tun_dst = match->flow.tunnel.ip_dst;
> pin->fmd.metadata = match->flow.metadata;
> memcpy(pin->fmd.regs, match->flow.regs, sizeof pin->fmd.regs);
> + pin->fmd.pkt_mark = match->flow.pkt_mark;
> }
>
> enum ofperr
> @@ -3031,6 +3038,10 @@ ofputil_packet_in_to_match(const struct
> ofputil_packet_in *pin,
> }
> }
>
> + if (pin->fmd.pkt_mark != 0) {
> + match_set_pkt_mark(match, pin->fmd.pkt_mark);
> + }
> +
> match_set_in_port(match, pin->fmd.in_port);
> }
>
> diff --git a/tests/ofproto.at b/tests/ofproto.at
> index e2e6f1b..38bfb02 100644
> --- a/tests/ofproto.at
> +++ b/tests/ofproto.at
> @@ -1563,14 +1563,14 @@ ovs-appctl -t ovs-ofctl ofctl/set-output-file
> monitor.log
> AT_CAPTURE_FILE([monitor.log])
>
> # Send a packet-out with a load action to set some metadata, and forward
> to controller
> -AT_CHECK([ovs-ofctl packet-out br0 controller
> 'load(0xfafafafa5a5a5a5a->OXM_OF_METADATA[[0..63]]), controller'
> '0001020304050010203040501234'])
> +AT_CHECK([ovs-ofctl packet-out br0 controller
> 'load(0xfafafafa5a5a5a5a->OXM_OF_METADATA[[0..63]]),
> load(0xaa->NXM_NX_PKT_MARK[[]]), controller'
> '0001020304050010203040501234'])
>
> # Stop the monitor and check its output.
> ovs-appctl -t ovs-ofctl ofctl/barrier
> ovs-appctl -t ovs-ofctl exit
>
> AT_CHECK([sed 's/ (xid=0x[[0-9a-fA-F]]*)//' monitor.log], [0], [dnl
> -NXT_PACKET_IN: total_len=14 in_port=CONTROLLER
> metadata=0xfafafafa5a5a5a5a (via action) data_len=14 (unbuffered)
> +NXT_PACKET_IN: total_len=14 in_port=CONTROLLER
> metadata=0xfafafafa5a5a5a5a pkt_mark=0xaa (via action) data_len=14
> (unbuffered)
>
> metadata=0,in_port=0,vlan_tci=0x0000,dl_src=00:10:20:30:40:50,dl_dst=00:01:02:03:04:05,dl_type=0x1234
> OFPT_BARRIER_REPLY:
> ])
> diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
> index 5e3441d..996ea06 100644
> --- a/tests/ovs-ofctl.at
> +++ b/tests/ovs-ofctl.at
> @@ -12,7 +12,7 @@ for test_case in \
> 'metadata=0 NXM,OXM' \
> 'in_port=1 any' \
> 'skb_priority=0 none' \
> - 'pkt_mark=1 none' \
> + 'pkt_mark=1 NXM,OXM' \
> 'reg0=0 NXM,OXM' \
> 'reg1=1 NXM,OXM' \
> 'reg2=2 NXM,OXM' \
> @@ -180,9 +180,9 @@ AT_CHECK([ovs-ofctl parse-flows flows.txt
> AT_CLEANUP
>
>
> -AT_SETUP([ovs-ofctl parse-flows (pkt_mark and skb_priority)])
> +AT_SETUP([ovs-ofctl parse-flows (skb_priority)])
> AT_DATA([flows.txt], [[
> -pkt_mark=0x12345678,skb_priority=0x12341234,tcp,tp_src=123,actions=flood
> +skb_priority=0x12341234,tcp,tp_src=123,actions=flood
> ]])
>
> AT_CHECK([ovs-ofctl parse-flows flows.txt
> @@ -197,6 +197,7 @@ AT_DATA([flows.txt], [[
> # comment
> tcp,tp_src=123,actions=flood
> in_port=LOCAL dl_vlan=9 dl_src=00:0A:E4:25:6B:B0 actions=drop
> +pkt_mark=0xbb,actions=set_field:0xaa->pkt_mark
> udp dl_vlan_pcp=7 idle_timeout=5 actions=strip_vlan output:0
> tcp,nw_src=192.168.0.3,tp_dst=80 actions=set_queue:37,output:1
> udp,nw_src=192.168.0.3,tp_dst=53 actions=pop_queue,output:1
> @@ -232,6 +233,7 @@ AT_CHECK([[sed 's/ (xid=0x[0-9a-fA-F]*)//' stdout]],
> [0],
> chosen protocol: NXM+table_id
> NXT_FLOW_MOD: ADD table:255 tcp,tp_src=123 actions=FLOOD
> NXT_FLOW_MOD: ADD table:255
> in_port=LOCAL,dl_vlan=9,dl_src=00:0a:e4:25:6b:b0 actions=drop
> +NXT_FLOW_MOD: ADD table:255 pkt_mark=0xbb
> actions=load:0xaa->NXM_NX_PKT_MARK[]
> NXT_FLOW_MOD: ADD table:255 udp,dl_vlan_pcp=7 idle:5
> actions=strip_vlan,output:0
> NXT_FLOW_MOD: ADD table:255 tcp,nw_src=192.168.0.3,tp_dst=80
> actions=set_queue:37,output:1
> NXT_FLOW_MOD: ADD table:255 udp,nw_src=192.168.0.3,tp_dst=53
> actions=pop_queue,output:1
> diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in
> index 3e6c7fe..447d71c 100644
> --- a/utilities/ovs-ofctl.8.in
> +++ b/utilities/ovs-ofctl.8.in
> @@ -806,6 +806,13 @@ exactly, and a 0-bit wildcards that bit.
> When a packet enters an OpenFlow switch, all of the registers are set
> to 0. Only explicit Nicira extension actions change register values.
> .
> +.IP \fBpkt_mark=\fIvalue\fR[\fB/\fImask\fR]
> +Matches packet metadata mark \fIvalue\fR either exactly or with optional
> +\fImask\fR. The mark is associated data that may be passed into other
> +system components in order to facilitate interaction between subsystems.
> +On Linux this corresponds to the skb mark but the exact implementation is
> +platform-dependent.
> +.
> .PP
> Defining IPv6 flows (those with \fBdl_type\fR equal to 0x86dd) requires
> support for NXM. The following shorthand notations are available for
> --
> 1.8.1.2
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openvswitch.org/pipermail/ovs-dev/attachments/20130813/3be5b3f3/attachment-0003.html>
More information about the dev
mailing list