Skip to content

Commit

Permalink
ofproto: add support of OFPR_GROUP as packet-in reason for OF1.4+
Browse files Browse the repository at this point in the history
When the Packet-In message is triggered by a group action, OFPR_GROUP is
passed internally as the reason. The wire_reason() function converts the
reason to OFPR_ACTION if the wire protocol is earlier than OF1.4.

The wire_reason() function also converts other unsupported reasons
(i.e., OFPR_ACTION_SET and OFPR_PACKET_OUT) to OFPR_ACTION if it detects
a wire protocol earlier than OF1.4.

By default reason code OFPR_GROUP for Packet-In will be enabled for
async messages as in ofconn_flush(). Upon a connection being established
with a controller, the protocol version is checked and OFPR_GROUP will
be disabled in async config if the protocol is lower than OF1.4. Any
controller running OF1.4+ is still be able to enable OFPR_GROUP at its
will without being affected by this check.

The patch also includes tests cases for both OF1.3 and OF1.4 to ensure
proper reason code is given for packet-in message triggered by group
action.

Signed-off-by: Shu Shen <[email protected]>
Signed-off-by: Ben Pfaff <[email protected]>
  • Loading branch information
shushen authored and blp committed Dec 12, 2014
1 parent 4819e33 commit 3a11fd5
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 9 deletions.
1 change: 1 addition & 0 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ sent, an entry labeled "---" means that the message is suppressed.
OFPR_NO_MATCH yes ---
OFPR_ACTION yes ---
OFPR_INVALID_TTL --- ---
OFPR_GROUP (OF1.4+) yes ---
OFPT_FLOW_REMOVED / NXT_FLOW_REMOVED
OFPRR_IDLE_TIMEOUT yes ---
Expand Down
1 change: 1 addition & 0 deletions OPENFLOW-1.1+.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ OpenFlow 1.4 features are listed in the previous section.
* More descriptive reasons for packet-in
Distinguish OFPR_APPLY_ACTION, OFPR_ACTION_SET, OFPR_GROUP,
OFPR_PACKET_OUT. NO_MATCH was renamed to OFPR_TABLE_MISS.
(OFPR_GROUP is now supported)
[EXT-136]
[required for OF1.4+]

Expand Down
48 changes: 40 additions & 8 deletions ofproto/connmgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -996,6 +996,14 @@ void
ofconn_set_protocol(struct ofconn *ofconn, enum ofputil_protocol protocol)
{
ofconn->protocol = protocol;
if (!(protocol & OFPUTIL_P_OF14_UP)) {
uint32_t *master = ofconn->master_async_config;
uint32_t *slave = ofconn->slave_async_config;

/* OFPR_GROUP is not supported before OF1.4 */
master[OAM_PACKET_IN] &= ~(1u << OFPR_GROUP);
slave [OAM_PACKET_IN] &= ~(1u << OFPR_GROUP);
}
}

/* Returns the currently configured packet in format for 'ofconn', one of
Expand Down Expand Up @@ -1056,6 +1064,13 @@ ofconn_get_async_config(struct ofconn *ofconn,
uint32_t *master_masks, uint32_t *slave_masks)
{
size_t size = sizeof ofconn->master_async_config;

/* Make sure we know the protocol version and the async_config
* masks are properly updated by calling ofconn_get_protocol() */
if (OFPUTIL_P_NONE == ofconn_get_protocol(ofconn)){
OVS_NOT_REACHED();
}

memcpy(master_masks, ofconn->master_async_config, size);
memcpy(slave_masks, ofconn->slave_async_config, size);
}
Expand Down Expand Up @@ -1235,7 +1250,9 @@ ofconn_flush(struct ofconn *ofconn)
/* "master" and "other" roles get all asynchronous messages by default,
* except that the controller needs to enable nonstandard "packet-in"
* reasons itself. */
master[OAM_PACKET_IN] = (1u << OFPR_NO_MATCH) | (1u << OFPR_ACTION);
master[OAM_PACKET_IN] = ((1u << OFPR_NO_MATCH)
| (1u << OFPR_ACTION)
| (1u << OFPR_GROUP));
master[OAM_PORT_STATUS] = ((1u << OFPPR_ADD)
| (1u << OFPPR_DELETE)
| (1u << OFPPR_MODIFY));
Expand Down Expand Up @@ -1651,16 +1668,31 @@ connmgr_send_flow_removed(struct connmgr *mgr,
static enum ofp_packet_in_reason
wire_reason(struct ofconn *ofconn, const struct ofproto_packet_in *pin)
{
if (pin->miss_type == OFPROTO_PACKET_IN_MISS_FLOW
&& pin->up.reason == OFPR_ACTION) {
enum ofputil_protocol protocol = ofconn_get_protocol(ofconn);
enum ofputil_protocol protocol = ofconn_get_protocol(ofconn);

if (protocol != OFPUTIL_P_NONE
&& ofputil_protocol_to_ofp_version(protocol) >= OFP13_VERSION) {
return OFPR_NO_MATCH;
if (pin->miss_type == OFPROTO_PACKET_IN_MISS_FLOW
&& pin->up.reason == OFPR_ACTION
&& protocol != OFPUTIL_P_NONE
&& ofputil_protocol_to_ofp_version(protocol) >= OFP13_VERSION) {
return OFPR_NO_MATCH;
}

switch (pin->up.reason) {
case OFPR_ACTION_SET:
case OFPR_GROUP:
case OFPR_PACKET_OUT:
if (!(protocol & OFPUTIL_P_OF14_UP)) {
/* Only supported in OF1.4+ */
return OFPR_ACTION;
}
/* Fall through. */
case OFPR_NO_MATCH:
case OFPR_ACTION:
case OFPR_INVALID_TTL:
case OFPR_N_REASONS:
default:
return pin->up.reason;
}
return pin->up.reason;
}

/* Given 'pin', sends an OFPT_PACKET_IN message to each OpenFlow controller as
Expand Down
3 changes: 2 additions & 1 deletion ofproto/ofproto-dpif-xlate.c
Original file line number Diff line number Diff line change
Expand Up @@ -3405,7 +3405,8 @@ xlate_output_action(struct xlate_ctx *ctx,
flood_packets(ctx, true);
break;
case OFPP_CONTROLLER:
execute_controller_action(ctx, max_len, OFPR_ACTION, 0);
execute_controller_action(ctx, max_len,
ctx->in_group ? OFPR_GROUP : OFPR_ACTION, 0);
break;
case OFPP_NONE:
break;
Expand Down
88 changes: 88 additions & 0 deletions tests/ofproto-dpif.at
Original file line number Diff line number Diff line change
Expand Up @@ -2746,6 +2746,94 @@ OVS_VSWITCHD_STOP
AT_CLEANUP



AT_SETUP([ofproto-dpif - packet-in reason in group table (Openflow 1.3)])
OVS_VSWITCHD_START([dnl
add-port br0 p1 -- set Interface p1 type=dummy
])
ON_EXIT([kill `cat ovs-ofctl.pid`])

AT_CAPTURE_FILE([ofctl_monitor.log])
# A table-miss flow has priority 0 and no match
AT_CHECK([ovs-ofctl --protocols=OpenFlow13 add-group br0 'group_id=1234,type=all,bucket=output:10,bucket=output:CONTROLLER'])
AT_CHECK([ovs-ofctl --protocols=OpenFlow13 add-flow br0 'in_port=1 actions=group:1234'])

dnl Singleton controller action.
AT_CHECK([ovs-ofctl monitor -P openflow10 --protocols=OpenFlow13 br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3 ; do
ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=10:11:11:11:11:11,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=10),tcp_flags(0x002)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
ovs-appctl -t ovs-ofctl exit

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (OF1.3) (xid=0x0): cookie=0x0 total_len=60 in_port=1 (via action) data_len=60 (unbuffered)
tcp,in_port=0,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:0
dnl
OFPT_PACKET_IN (OF1.3) (xid=0x0): cookie=0x0 total_len=60 in_port=1 (via action) data_len=60 (unbuffered)
tcp,in_port=0,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:0
dnl
OFPT_PACKET_IN (OF1.3) (xid=0x0): cookie=0x0 total_len=60 in_port=1 (via action) data_len=60 (unbuffered)
tcp,in_port=0,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:0
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

AT_CHECK([ovs-ofctl --protocols=OpenFlow13 dump-flows br0 | ofctl_strip | sort], [0], [dnl
n_packets=3, n_bytes=180, in_port=1 actions=group:1234
OFPST_FLOW reply (OF1.3):
])

OVS_VSWITCHD_STOP
AT_CLEANUP


AT_SETUP([ofproto-dpif - packet-in reason in group table (Openflow 1.4)])
OVS_VSWITCHD_START([dnl
add-port br0 p1 -- set Interface p1 type=dummy
])
ON_EXIT([kill `cat ovs-ofctl.pid`])

AT_CAPTURE_FILE([ofctl_monitor.log])
# A table-miss flow has priority 0 and no match
AT_CHECK([ovs-ofctl --protocols=OpenFlow14 add-group br0 'group_id=1234,type=all,bucket=output:10,bucket=output:CONTROLLER'])
AT_CHECK([ovs-ofctl --protocols=OpenFlow14 add-flow br0 'in_port=1 actions=group:1234'])

dnl Singleton controller action.
AT_CHECK([ovs-ofctl monitor -P openflow10 --protocols=OpenFlow14 br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log])

for i in 1 2 3 ; do
ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=10:11:11:11:11:11,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=10),tcp_flags(0x002)'
done
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
ovs-appctl -t ovs-ofctl exit

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

AT_CHECK([cat ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (OF1.4) (xid=0x0): cookie=0x0 total_len=60 in_port=1 (via group) data_len=60 (unbuffered)
tcp,in_port=0,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:0
dnl
OFPT_PACKET_IN (OF1.4) (xid=0x0): cookie=0x0 total_len=60 in_port=1 (via group) data_len=60 (unbuffered)
tcp,in_port=0,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:0
dnl
OFPT_PACKET_IN (OF1.4) (xid=0x0): cookie=0x0 total_len=60 in_port=1 (via group) data_len=60 (unbuffered)
tcp,in_port=0,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=syn tcp_csum:0
])

AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])

AT_CHECK([ovs-ofctl --protocols=OpenFlow14 dump-flows br0 | ofctl_strip | sort], [0], [dnl
n_packets=3, n_bytes=180, in_port=1 actions=group:1234
OFPST_FLOW reply (OF1.4):
])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ofproto-dpif - ARP modification slow-path])
OVS_VSWITCHD_START
ADD_OF_PORTS([br0], [1], [2])
Expand Down

0 comments on commit 3a11fd5

Please sign in to comment.