mirror of
https://github.com/openvswitch/ovs
synced 2025-10-27 15:18:06 +00:00
ofp-util: Implement OpenFlow 1.1 packet-in message.
Signed-off-by: Ben Pfaff <blp@nicira.com> Reviewed-by: Simon Horman <horms@verge.net.au>
This commit is contained in:
47
DESIGN
47
DESIGN
@@ -266,6 +266,53 @@ OpenFlow 1.3 makes these changes:
|
||||
The table for 1.3 is the same as the one shown above for 1.2.
|
||||
|
||||
|
||||
OFPT_PACKET_IN
|
||||
==============
|
||||
|
||||
The OpenFlow 1.1 specification for OFPT_PACKET_IN is confusing. The
|
||||
definition in OF1.1 openflow.h is[*]:
|
||||
|
||||
/* Packet received on port (datapath -> controller). */
|
||||
struct ofp_packet_in {
|
||||
struct ofp_header header;
|
||||
uint32_t buffer_id; /* ID assigned by datapath. */
|
||||
uint32_t in_port; /* Port on which frame was received. */
|
||||
uint32_t in_phy_port; /* Physical Port on which frame was received. */
|
||||
uint16_t total_len; /* Full length of frame. */
|
||||
uint8_t reason; /* Reason packet is being sent (one of OFPR_*) */
|
||||
uint8_t table_id; /* ID of the table that was looked up */
|
||||
uint8_t data[0]; /* Ethernet frame, halfway through 32-bit word,
|
||||
so the IP header is 32-bit aligned. The
|
||||
amount of data is inferred from the length
|
||||
field in the header. Because of padding,
|
||||
offsetof(struct ofp_packet_in, data) ==
|
||||
sizeof(struct ofp_packet_in) - 2. */
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct ofp_packet_in) == 24);
|
||||
|
||||
The confusing part is the comment on the data[] member. This comment
|
||||
is a leftover from OF1.0 openflow.h, in which the comment was correct:
|
||||
sizeof(struct ofp_packet_in) is 20 in OF1.0 and offsetof(struct
|
||||
ofp_packet_in, data) is 18. When OF1.1 was written, the structure
|
||||
members were changed but the comment was carelessly not updated, and
|
||||
the comment became wrong: sizeof(struct ofp_packet_in) and
|
||||
offsetof(struct ofp_packet_in, data) are both 24 in OF1.1.
|
||||
|
||||
That leaves the question of how to implement ofp_packet_in in OF1.1.
|
||||
The OpenFlow reference implementation for OF1.1 does not include any
|
||||
padding, that is, the first byte of the encapsulated frame immediately
|
||||
follows the 'table_id' member without a gap. Open vSwitch therefore
|
||||
implements it the same way for compatibility.
|
||||
|
||||
For an earlier discussion, please see the thread archived at:
|
||||
https://mailman.stanford.edu/pipermail/openflow-discuss/2011-August/002604.html
|
||||
|
||||
[*] The quoted definition is directly from OF1.1. Definitions used
|
||||
inside OVS omit the 8-byte ofp_header members, so the sizes in
|
||||
this discussion are 8 bytes larger than those declared in OVS
|
||||
header files.
|
||||
|
||||
|
||||
VLAN Matching
|
||||
=============
|
||||
|
||||
|
||||
@@ -54,13 +54,6 @@ OpenFlow 1.1
|
||||
The list of remaining work items for OpenFlow 1.1 is below. It is
|
||||
probably incomplete.
|
||||
|
||||
* The new in_phy_port field in OFPT_PACKET_IN needs some kind of
|
||||
implementation. It has a sensible interpretation for tunnels
|
||||
but in general the physical port is not in the datapath for OVS
|
||||
so the value is not necessarily meaningful. We might have to
|
||||
just fix it as the same as in_port.
|
||||
[required for OF1.1; optional for OF1.2+]
|
||||
|
||||
* OFPT_TABLE_MOD message. This is new in OF1.1, so we need to
|
||||
implement it. It should be implemented so that the default OVS
|
||||
behavior does not change.
|
||||
|
||||
@@ -741,12 +741,7 @@ struct ofp11_packet_in {
|
||||
ovs_be16 total_len; /* Full length of frame. */
|
||||
uint8_t reason; /* Reason packet is being sent (one of OFPR_*) */
|
||||
uint8_t table_id; /* ID of the table that was looked up */
|
||||
/* uint8_t data[0]; Ethernet frame, halfway through 32-bit word,
|
||||
so the IP header is 32-bit aligned. The
|
||||
amount of data is inferred from the length
|
||||
field in the header. Because of padding,
|
||||
offsetof(struct ofp_packet_in, data) ==
|
||||
sizeof(struct ofp_packet_in) - 2. */
|
||||
/* Followed by Ethernet frame. */
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct ofp11_packet_in) == 16);
|
||||
|
||||
|
||||
@@ -3196,6 +3196,23 @@ ofputil_decode_packet_in(struct ofputil_packet_in *pin,
|
||||
pin->reason = opi->reason;
|
||||
pin->buffer_id = ntohl(opi->buffer_id);
|
||||
pin->total_len = ntohs(opi->total_len);
|
||||
} else if (raw == OFPRAW_OFPT11_PACKET_IN) {
|
||||
const struct ofp11_packet_in *opi;
|
||||
enum ofperr error;
|
||||
|
||||
opi = ofpbuf_pull(&b, sizeof *opi);
|
||||
|
||||
pin->packet = b.data;
|
||||
pin->packet_len = b.size;
|
||||
|
||||
pin->buffer_id = ntohl(opi->buffer_id);
|
||||
error = ofputil_port_from_ofp11(opi->in_port, &pin->fmd.in_port);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
pin->total_len = ntohs(opi->total_len);
|
||||
pin->reason = opi->reason;
|
||||
pin->table_id = opi->table_id;
|
||||
} else if (raw == OFPRAW_NXT_PACKET_IN) {
|
||||
const struct nx_packet_in *npi;
|
||||
struct match match;
|
||||
@@ -3309,6 +3326,27 @@ ofputil_encode_nx_packet_in(const struct ofputil_packet_in *pin)
|
||||
return packet;
|
||||
}
|
||||
|
||||
static struct ofpbuf *
|
||||
ofputil_encode_ofp11_packet_in(const struct ofputil_packet_in *pin)
|
||||
{
|
||||
struct ofp11_packet_in *opi;
|
||||
struct ofpbuf *packet;
|
||||
|
||||
packet = ofpraw_alloc_xid(OFPRAW_OFPT11_PACKET_IN, OFP11_VERSION,
|
||||
htonl(0), pin->packet_len);
|
||||
opi = ofpbuf_put_zeros(packet, sizeof *opi);
|
||||
opi->buffer_id = htonl(pin->buffer_id);
|
||||
opi->in_port = ofputil_port_to_ofp11(pin->fmd.in_port);
|
||||
opi->in_phy_port = opi->in_port;
|
||||
opi->total_len = htons(pin->total_len);
|
||||
opi->reason = pin->reason;
|
||||
opi->table_id = pin->table_id;
|
||||
|
||||
ofpbuf_put(packet, pin->packet, pin->packet_len);
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
static struct ofpbuf *
|
||||
ofputil_encode_ofp12_packet_in(const struct ofputil_packet_in *pin,
|
||||
enum ofputil_protocol protocol)
|
||||
@@ -3373,7 +3411,8 @@ ofputil_encode_packet_in(const struct ofputil_packet_in *pin,
|
||||
break;
|
||||
|
||||
case OFPUTIL_P_OF11_STD:
|
||||
NOT_REACHED();
|
||||
packet = ofputil_encode_ofp11_packet_in(pin);
|
||||
break;
|
||||
|
||||
case OFPUTIL_P_OF12_OXM:
|
||||
case OFPUTIL_P_OF13_OXM:
|
||||
|
||||
@@ -469,6 +469,21 @@ tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:54:00:00:00:05,dl_dst=50:54:0
|
||||
])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([OFPT_PACKET_IN - OF1.1])
|
||||
AT_KEYWORDS([ofp-print])
|
||||
AT_CHECK([ovs-ofctl ofp-print "\
|
||||
02 0a 00 54 00 00 00 00 00 00 01 11 00 00 00 03 \
|
||||
00 00 00 03 00 3c 00 00 \
|
||||
50 54 00 00 00 06 50 54 00 00 00 05 08 00 \
|
||||
45 00 00 28 bd 12 00 00 40 06 3c 6a c0 a8 00 01 \
|
||||
c0 a8 00 02 27 2f 00 00 78 50 cc 5b 57 af 42 1e \
|
||||
50 02 02 00 26 e8 00 00 00 00 00 00 00 00 \
|
||||
"], [0], [dnl
|
||||
OFPT_PACKET_IN (OF1.1) (xid=0x0): total_len=60 in_port=3 (via no_match) data_len=60 buffer=0x00000111
|
||||
tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:06,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=10031,tp_dst=0,tcp_flags=0x002 tcp_csum:26e8
|
||||
])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([OFPT_PACKET_IN - OF1.2])
|
||||
AT_KEYWORDS([ofp-print])
|
||||
AT_CHECK([ovs-ofctl ofp-print "\
|
||||
|
||||
@@ -1757,6 +1757,39 @@ OFPT_BARRIER_REPLY (OF1.2):
|
||||
OVS_VSWITCHD_STOP
|
||||
AT_CLEANUP
|
||||
|
||||
dnl This test checks that OFPT_PACKET_OUT accepts both OFPP_NONE (as
|
||||
dnl specified by OpenFlow 1.1) and OFPP_CONTROLLER (used by some
|
||||
dnl controllers despite the spec) as meaning a packet that was generated
|
||||
dnl by the controller.
|
||||
AT_SETUP([ofproto - packet-out from controller (OpenFlow 1.1)])
|
||||
OVS_VSWITCHD_START
|
||||
|
||||
# Start a monitor listening for packet-ins.
|
||||
AT_CHECK([ovs-ofctl -O OpenFlow11 monitor br0 --detach --no-chdir --pidfile])
|
||||
ovs-appctl -t ovs-ofctl ofctl/send 0209000c0123456700000080
|
||||
ovs-appctl -t ovs-ofctl ofctl/barrier
|
||||
ovs-appctl -t ovs-ofctl ofctl/set-output-file monitor.log
|
||||
AT_CAPTURE_FILE([monitor.log])
|
||||
|
||||
# Send some packet-outs with OFPP_NONE and OFPP_CONTROLLER (65533) as in_port.
|
||||
AT_CHECK([ovs-ofctl -O OpenFlow11 packet-out br0 none controller '0001020304050010203040501234'])
|
||||
AT_CHECK([ovs-ofctl -O OpenFlow11 packet-out br0 4294967293 controller '0001020304050010203040505678'])
|
||||
|
||||
# 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.1): total_len=14 in_port=ANY (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_PACKET_IN (OF1.1): total_len=14 in_port=CONTROLLER (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=0x5678
|
||||
OFPT_BARRIER_REPLY (OF1.1):
|
||||
])
|
||||
|
||||
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)])
|
||||
|
||||
Reference in New Issue
Block a user