@@ -1424,6 +1424,8 @@ void
flow_wildcards_init_for_packet(struct flow_wildcards *wc,
const struct flow *flow)
{
+ ovs_be16 dl_type = OVS_BE16_MAX;
+
memset(&wc->masks, 0x0, sizeof wc->masks);
/* Update this function whenever struct flow changes. */
@@ -1475,26 +1477,29 @@ flow_wildcards_init_for_packet(struct flow_wildcards *wc,
WC_MASK_FIELD(wc, in_port);
/* actset_output wildcarded. */
-
- WC_MASK_FIELD(wc, dl_dst);
- WC_MASK_FIELD(wc, dl_src);
- WC_MASK_FIELD(wc, dl_type);
-
- /* No need to set mask of inner VLANs that don't exist. */
- for (int i = 0; i < FLOW_MAX_VLAN_HEADERS; i++) {
- /* Always show the first zero VLAN. */
- WC_MASK_FIELD(wc, vlans[i]);
- if (flow->vlans[i].tci == htons(0)) {
- break;
+ if (flow->packet_type == htonl(PT_ETH)) {
+ WC_MASK_FIELD(wc, dl_dst);
+ WC_MASK_FIELD(wc, dl_src);
+ WC_MASK_FIELD(wc, dl_type);
+ /* No need to set mask of inner VLANs that don't exist. */
+ for (int i = 0; i < FLOW_MAX_VLAN_HEADERS; i++) {
+ /* Always show the first zero VLAN. */
+ WC_MASK_FIELD(wc, vlans[i]);
+ if (flow->vlans[i].tci == htons(0)) {
+ break;
+ }
}
+ dl_type = flow->dl_type;
+ } else {
+ dl_type = pt_ns_type_be(flow->packet_type);
}
- if (flow->dl_type == htons(ETH_TYPE_IP)) {
+ if (dl_type == htons(ETH_TYPE_IP)) {
WC_MASK_FIELD(wc, nw_src);
WC_MASK_FIELD(wc, nw_dst);
WC_MASK_FIELD(wc, ct_nw_src);
WC_MASK_FIELD(wc, ct_nw_dst);
- } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
+ } else if (dl_type == htons(ETH_TYPE_IPV6)) {
WC_MASK_FIELD(wc, ipv6_src);
WC_MASK_FIELD(wc, ipv6_dst);
WC_MASK_FIELD(wc, ipv6_label);
@@ -1506,15 +1511,15 @@ flow_wildcards_init_for_packet(struct flow_wildcards *wc,
WC_MASK_FIELD(wc, ct_ipv6_src);
WC_MASK_FIELD(wc, ct_ipv6_dst);
}
- } else if (flow->dl_type == htons(ETH_TYPE_ARP) ||
- flow->dl_type == htons(ETH_TYPE_RARP)) {
+ } else if (dl_type == htons(ETH_TYPE_ARP) ||
+ dl_type == htons(ETH_TYPE_RARP)) {
WC_MASK_FIELD(wc, nw_src);
WC_MASK_FIELD(wc, nw_dst);
WC_MASK_FIELD(wc, nw_proto);
WC_MASK_FIELD(wc, arp_sha);
WC_MASK_FIELD(wc, arp_tha);
return;
- } else if (eth_type_mpls(flow->dl_type)) {
+ } else if (eth_type_mpls(dl_type)) {
for (int i = 0; i < FLOW_MAX_MPLS_LABELS; i++) {
WC_MASK_FIELD(wc, mpls_lse[i]);
if (flow->mpls_lse[i] & htonl(MPLS_BOS_MASK)) {
@@ -661,6 +661,19 @@ parse_ofp_packet_out_str__(struct ofputil_packet_out *po, char *string,
goto out;
}
match_set_in_port(&po->flow_metadata, in_port);
+ } else if (!strcmp(name, "packet_type")) {
+ char *ns = value;
+ char *ns_type = strstr(value, ",");
+ if (ns_type) {
+ ovs_be32 packet_type;
+ *ns_type = '\0';
+ packet_type = PACKET_TYPE_BE(strtoul(ns, NULL, 0),
+ strtoul(++ns_type,NULL, 0));
+ match_set_packet_type(&po->flow_metadata, packet_type);
+ } else {
+ error = xasprintf("%s(%s) can't be interpreted", name, value);
+ goto out;
+ }
} else if (!strcmp(name, "packet")) {
const char *error_msg = eth_from_hex(value, &packet);
if (error_msg) {
@@ -256,9 +256,9 @@ ofp_print_packet_out(struct ds *string, const struct ofp_header *oh,
if (po.buffer_id == UINT32_MAX) {
ds_put_format(string, " data_len=%"PRIuSIZE, po.packet_len);
if (verbosity > 0 && po.packet_len > 0) {
- /* Packet Out can only carry Ethernet packets. */
+ ovs_be32 po_packet_type = po.flow_metadata.flow.packet_type;
char *packet = ofp_packet_to_string(po.packet, po.packet_len,
- htonl(PT_ETH));
+ po_packet_type);
ds_put_char(string, '\n');
ds_put_cstr(string, packet);
free(packet);
@@ -4238,6 +4238,7 @@ ofputil_decode_packet_out(struct ofputil_packet_out *po,
if (error) {
return error;
}
+ match_set_packet_type(&po->flow_metadata, htonl(PT_ETH));
match_set_in_port(&po->flow_metadata, in_port);
error = ofpacts_pull_openflow_actions(&b, ntohs(opo->actions_len),
@@ -4251,6 +4252,7 @@ ofputil_decode_packet_out(struct ofputil_packet_out *po,
const struct ofp10_packet_out *opo = ofpbuf_pull(&b, sizeof *opo);
po->buffer_id = ntohl(opo->buffer_id);
+ match_set_packet_type(&po->flow_metadata, htonl(PT_ETH));
match_set_in_port(&po->flow_metadata, u16_to_ofp(ntohs(opo->in_port)));
error = ofpacts_pull_openflow_actions(&b, ntohs(opo->actions_len),
@@ -3479,9 +3479,18 @@ ofproto_packet_out_init(struct ofproto *ofproto,
return OFPERR_OFPBRC_BUFFER_UNKNOWN;
}
+ /* NON-PTAP bridge should accept only Ethernet packet. */
+ if (!ofproto->packet_type_aware &&
+ po->flow_metadata.flow.packet_type != htonl(PT_ETH)) {
+ return OFPERR_OFPBRC_BAD_PACKET;
+ }
+
/* Ensure that the L3 header is 32-bit aligned. */
opo->packet = dp_packet_clone_data_with_headroom(po->packet,
po->packet_len, 2);
+ /* Take the received packet_tpye as packet_type of the packet. */
+ opo->packet->packet_type = po->flow_metadata.flow.packet_type;
+
/* Store struct flow. */
opo->flow = xmalloc(sizeof *opo->flow);
*opo->flow = po->flow_metadata.flow;
@@ -731,7 +731,7 @@ b9 7c c0 a8 00 02 c0 a8 00 01 00 00 2b 60 00 00 \
00 00 6a 4f 2b 58 50 14 00 00 6d 75 00 00 00 00 \
00 00 00 00 \
"], [0], [dnl
-OFPT_PACKET_OUT (xid=0x0): in_port=1 actions=output:3 buffer=0x00000114
+OFPT_PACKET_OUT (xid=0x0): packet_type=(0,0),in_port=1 actions=output:3 buffer=0x00000114
])
AT_CLEANUP
@@ -745,7 +745,7 @@ b9 7c c0 a8 00 02 c0 a8 00 01 00 00 2b 60 00 00 \
00 00 6a 4f 2b 58 50 14 00 00 6d 75 00 00 00 00 \
00 00 00 00 \
"], [0], [dnl
-OFPT_PACKET_OUT (xid=0x0): in_port=1 actions=output:3 data_len=60
+OFPT_PACKET_OUT (xid=0x0): packet_type=(0,0),in_port=1 actions=output:3 data_len=60
tcp,vlan_tci=0x0000,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=0,tp_dst=11104,tcp_flags=rst|ack tcp_csum:6d75
])
AT_CLEANUP
@@ -760,7 +760,7 @@ b9 7c c0 a8 00 02 c0 a8 00 01 00 00 2b 60 00 00 \
00 00 6a 4f 2b 58 50 14 00 00 6d 75 00 00 00 00 \
00 00 00 00 \
" 3], [0], [dnl
-OFPT_PACKET_OUT (xid=0x0): in_port=1 actions=output:3 data_len=60
+OFPT_PACKET_OUT (xid=0x0): packet_type=(0,0),in_port=1 actions=output:3 data_len=60
tcp,vlan_tci=0x0000,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=0,tp_dst=11104,tcp_flags=rst|ack tcp_csum:6d75
00000000 50 54 00 00 00 05 50 54-00 00 00 06 08 00 45 00
00000010 00 28 00 00 40 00 40 06-b9 7c c0 a8 00 02 c0 a8
@@ -776,7 +776,7 @@ AT_CHECK([ovs-ofctl ofp-print "\
00 10 00 00 00 00 00 00 00 00 00 10 ff ff ff fb \
05 dc 00 00 00 00 00 00 \
"], [0], [dnl
-OFPT_PACKET_OUT (OF1.2) (xid=0x8858dfc5): in_port=LOCAL actions=FLOOD buffer=0xffffff00
+OFPT_PACKET_OUT (OF1.2) (xid=0x8858dfc5): packet_type=(0,0),in_port=LOCAL actions=FLOOD buffer=0xffffff00
])
AT_CLEANUP
@@ -791,7 +791,7 @@ b9 7c c0 a8 00 02 c0 a8 00 01 00 00 2b 60 00 00 \
00 00 6a 4f 2b 58 50 14 00 00 6d 75 00 00 00 00 \
00 00 00 00 \
"], [0], [dnl
-OFPT_PACKET_OUT (OF1.2) (xid=0x8858dfc5): in_port=LOCAL actions=FLOOD data_len=60
+OFPT_PACKET_OUT (OF1.2) (xid=0x8858dfc5): packet_type=(0,0),in_port=LOCAL actions=FLOOD data_len=60
tcp,vlan_tci=0x0000,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=0,tp_dst=11104,tcp_flags=rst|ack tcp_csum:6d75
])
AT_CLEANUP
@@ -3670,7 +3670,7 @@ b9 7c c0 a8 00 02 c0 a8 00 01 00 00 2b 60 00 00 \
"], [0], [dnl
OFPT_BUNDLE_ADD_MESSAGE (OF1.4) (xid=0x3):
bundle_id=0x1 flags=atomic
-OFPT_PACKET_OUT (OF1.4) (xid=0x3): in_port=LOCAL actions=FLOOD data_len=60
+OFPT_PACKET_OUT (OF1.4) (xid=0x3): packet_type=(0,0),in_port=LOCAL actions=FLOOD data_len=60
tcp,vlan_tci=0x0000,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=0,tp_dst=11104,tcp_flags=rst|ack tcp_csum:6d75
])
AT_CLEANUP
@@ -2141,7 +2141,7 @@ packet-out in_port=6, packet=0001020304050010203040501234 actions=table
packet-out in_port=6, packet=0001020304050010203040501234 actions=group:2
])
AT_CHECK([ovs-ofctl bundle br0 bundle.txt 2>&1 | sed '/talking to/,$d' | strip_xids], [], [dnl
-Error OFPBAC_BAD_OUT_GROUP for: OFPT_PACKET_OUT (OF1.4): in_port=6 actions=group:2 data_len=14
+Error OFPBAC_BAD_OUT_GROUP for: OFPT_PACKET_OUT (OF1.4): packet_type=(0,0),in_port=6 actions=group:2 data_len=14
vlan_tci=0x0000,dl_src=00:10:20:30:40:50,dl_dst=00:01:02:03:04:05,dl_type=0x1234
Error OFPBFC_MSG_FAILED for: OFPT_BUNDLE_CONTROL (OF1.4):
bundle_id=0 type=COMMIT_REQUEST flags=atomic ordered
@@ -4135,6 +4135,114 @@ OFPT_BARRIER_REPLY:
OVS_VSWITCHD_STOP
AT_CLEANUP
+dnl This test checks that 1.5 packet_out is properly encoded/decoded.
+AT_SETUP([ofproto - packet-out with set_field metadata (OpenFlow 1.5)])
+OVS_VSWITCHD_START
+
+# Start a monitor listening for packet-ins.
+AT_CHECK([ovs-ofctl -P standard -O OpenFlow13 monitor br0 --detach --no-chdir --pidfile])
+ovs-appctl -t ovs-ofctl ofctl/send 0409000c0123456700000080
+ovs-appctl -t ovs-ofctl ofctl/barrier
+ovs-appctl -t ovs-ofctl ofctl/set-output-file monitor.log
+AT_CAPTURE_FILE([monitor.log])
+
+# Send a packet-out with a couple of set-field action to set some metadata, and forward to controller
+AT_CHECK([ovs-ofctl -O OpenFlow15 packet-out br0 CONTROLLER 'set_field:0xfafafafa5a5a5a5a->metadata, 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
+OFPT_PACKET_IN (OF1.3): total_len=14 metadata=0xfafafafa5a5a5a5a,in_port=CONTROLLER (via action) data_len=14 (unbuffered)
+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 (OF1.3):
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+dnl This test checks that packet_type PT_ETH is properly encoded/decoded in 1.5 packet_out.
+AT_SETUP([ofproto - packet-out with set_field metadata with packet_type PT_ETH (OpenFlow 1.5)])
+OVS_VSWITCHD_START
+
+# Start a monitor listening for packet-ins.
+AT_CHECK([ovs-ofctl -P standard -O OpenFlow13 monitor br0 --detach --no-chdir --pidfile])
+ovs-appctl -t ovs-ofctl ofctl/send 0409000c0123456700000080
+ovs-appctl -t ovs-ofctl ofctl/barrier
+ovs-appctl -t ovs-ofctl ofctl/set-output-file monitor.log
+AT_CAPTURE_FILE([monitor.log])
+
+# Send a packet-out with a couple of set-field action to set some metadata, and forward to controller
+AT_CHECK([ovs-ofctl -O OpenFlow15 packet-out br0 "in_port=controller packet=0001020304050010203040501234 packet_type(0,0x0) actions=set_field:0xfafafafa5a5a5a5a->metadata,controller"])
+
+# 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
+OFPT_PACKET_IN (OF1.3): total_len=14 metadata=0xfafafafa5a5a5a5a,in_port=CONTROLLER (via action) data_len=14 (unbuffered)
+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 (OF1.3):
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+dnl This test checks that packet_type PT_IPV4 is properly encoded/decoded in 1.5 packet_out.
+AT_SETUP([ofproto - packet-out with set_field metadata with packet_type PT_IPV4 on PTAP bridge (OpenFlow 1.5)])
+OVS_VSWITCHD_START
+
+AT_CHECK([
+ ovs-vsctl set bridge br0 other-config:packet-type-aware=true
+], [0])
+
+# Start a monitor listening for packet-ins.
+AT_CHECK([ovs-ofctl -P standard -O OpenFlow13 monitor br0 --detach --no-chdir --pidfile])
+ovs-appctl -t ovs-ofctl ofctl/send 0409000c0123456700000080
+ovs-appctl -t ovs-ofctl ofctl/barrier
+ovs-appctl -t ovs-ofctl ofctl/set-output-file monitor.log
+AT_CAPTURE_FILE([monitor.log])
+
+# Send a packet-out with a couple of set-field action to set some metadata, and forward to controller
+AT_CHECK([ovs-ofctl -O OpenFlow15 packet-out br0 "in_port=controller packet=4500002012344000ff1155670a0000140a00001e006400c8000cea78ffffffff packet_type(1,0x800) actions=set_field:0xfafafafa5a5a5a5a->metadata,controller"])
+
+# 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
+OFPT_PACKET_IN (OF1.3): total_len=32 packet_type=(1,0x800),metadata=0xfafafafa5a5a5a5a,in_port=CONTROLLER (via action) data_len=32 (unbuffered)
+nw_src=10.0.0.20,nw_dst=10.0.0.30,nw_proto=17,nw_tos=0,nw_ecn=0,nw_ttl=255,tp_src=100,tp_dst=200 udp_csum:ea78
+OFPT_BARRIER_REPLY (OF1.3):
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+dnl This test checks that NON-PTAP bridge rejects 1.5 packet-out with packet_type PT_IPV4.
+AT_SETUP([ofproto - packet-out with set_field metadata with packet_type PT_IPV4 on NON-PTAP bridge (OpenFlow 1.5)])
+OVS_VSWITCHD_START
+
+AT_CHECK([
+ ovs-vsctl set bridge br0 other-config:packet-type-aware=false
+], [0])
+
+AT_CHECK([ovs-ofctl -O OpenFlow15 packet-out br0 "in_port=controller packet=4500002012344000ff1155670a0000140a00001e006400c8000cea78ffffffff packet_type(1,0x800) actions=set_field:0xfafafafa5a5a5a5a->metadata,controller"],
+[1], [], [dnl
+OFPT_ERROR (OF1.5) (xid=0x4): OFPBRC_BAD_PACKET
+OFPT_PACKET_OUT (OF1.5) (xid=0x4):
+(***truncated to 64 bytes from 104***)
+00000000 06 0d 00 68 00 00 00 04-ff ff ff ff 00 20 00 00 |...h......... ..|
+00000010 00 01 00 14 80 00 58 04-00 01 08 00 80 00 00 04 |......X.........|
+00000020 ff ff ff fd 00 00 00 00-00 19 00 10 80 00 04 08 |................|
+00000030 fa fa fa fa 5a 5a 5a 5a-00 00 00 10 ff ff ff fd |....ZZZZ........|
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+
dnl This test checks that metadata is encoded in packet_in structures,
dnl supported by NXAST.
AT_SETUP([ofproto - packet-out with metadata (NXM)])
@@ -2198,6 +2198,7 @@ ofctl_packet_out(struct ovs_cmdl_context *ctx)
str_to_port_no(ctx->argv[1], ctx->argv[2]));
po.ofpacts = ofpacts.data;
po.ofpacts_len = ofpacts.size;
+ po.flow_metadata.flow.packet_type = htonl(PT_ETH);
protocol = open_vconn_for_flow_mod(ctx->argv[1], &vconn,
usable_protocols);