@@ -260,6 +260,7 @@ Eivind Bulie Haanaes
Eric Lopez elopez@nicira.com
Frido Roose fr.roose@gmail.com
Gaetano Catalli gaetano.catalli@gmail.com
+Gavin Remaley gavin_remaley@selinc.com
George Shuklin amarao@desunote.ru
Gerald Rogers gerald.rogers@intel.com
Ghanem Bahri bahri.ghanem@gmail.com
@@ -347,6 +347,68 @@ static char *OVS_WARN_UNUSED_RESULT ofpacts_parse(
char *str, struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols,
bool allow_instructions, enum ofpact_type outer_action);
+/* Returns the ofpact following 'ofpact', except that if 'ofpact' contains
+ * nested ofpacts it returns the first one. */
+struct ofpact *
+ofpact_next_flattened(const struct ofpact *ofpact)
+{
+ switch (ofpact->type) {
+ case OFPACT_OUTPUT:
+ case OFPACT_GROUP:
+ case OFPACT_CONTROLLER:
+ case OFPACT_ENQUEUE:
+ case OFPACT_OUTPUT_REG:
+ case OFPACT_BUNDLE:
+ case OFPACT_SET_FIELD:
+ case OFPACT_SET_VLAN_VID:
+ case OFPACT_SET_VLAN_PCP:
+ case OFPACT_STRIP_VLAN:
+ case OFPACT_PUSH_VLAN:
+ case OFPACT_SET_ETH_SRC:
+ case OFPACT_SET_ETH_DST:
+ case OFPACT_SET_IPV4_SRC:
+ case OFPACT_SET_IPV4_DST:
+ case OFPACT_SET_IP_DSCP:
+ case OFPACT_SET_IP_ECN:
+ case OFPACT_SET_IP_TTL:
+ case OFPACT_SET_L4_SRC_PORT:
+ case OFPACT_SET_L4_DST_PORT:
+ case OFPACT_REG_MOVE:
+ case OFPACT_STACK_PUSH:
+ case OFPACT_STACK_POP:
+ case OFPACT_DEC_TTL:
+ case OFPACT_SET_MPLS_LABEL:
+ case OFPACT_SET_MPLS_TC:
+ case OFPACT_SET_MPLS_TTL:
+ case OFPACT_DEC_MPLS_TTL:
+ case OFPACT_PUSH_MPLS:
+ case OFPACT_POP_MPLS:
+ case OFPACT_SET_TUNNEL:
+ case OFPACT_SET_QUEUE:
+ case OFPACT_POP_QUEUE:
+ case OFPACT_FIN_TIMEOUT:
+ case OFPACT_RESUBMIT:
+ case OFPACT_LEARN:
+ case OFPACT_CONJUNCTION:
+ case OFPACT_MULTIPATH:
+ case OFPACT_NOTE:
+ case OFPACT_EXIT:
+ case OFPACT_SAMPLE:
+ case OFPACT_UNROLL_XLATE:
+ case OFPACT_DEBUG_RECIRC:
+ case OFPACT_METER:
+ case OFPACT_CLEAR_ACTIONS:
+ case OFPACT_WRITE_METADATA:
+ case OFPACT_GOTO_TABLE:
+ return ofpact_next(ofpact);
+
+ case OFPACT_WRITE_ACTIONS:
+ return ofpact_get_WRITE_ACTIONS(ofpact)->actions;
+ }
+
+ OVS_NOT_REACHED();
+}
+
/* Pull off existing actions or instructions. Used by nesting actions to keep
* ofpacts_parse() oblivious of actions nesting.
*
@@ -6175,7 +6237,7 @@ ofpacts_output_to_port(const struct ofpact *ofpacts, size_t ofpacts_len,
{
const struct ofpact *a;
- OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
+ OFPACT_FOR_EACH_FLATTENED (a, ofpacts, ofpacts_len) {
if (ofpact_outputs_to_port(a, port)) {
return true;
}
@@ -6192,7 +6254,7 @@ ofpacts_output_to_group(const struct ofpact *ofpacts, size_t ofpacts_len,
{
const struct ofpact *a;
- OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
+ OFPACT_FOR_EACH_FLATTENED (a, ofpacts, ofpacts_len) {
if (a->type == OFPACT_GROUP
&& ofpact_get_GROUP(a)->group_id == group_id) {
return true;
@@ -183,12 +183,15 @@ BUILD_ASSERT_DECL(sizeof(struct ofpact) == 4);
#define OFPACT_ALIGNTO 8
#define OFPACT_ALIGN(SIZE) ROUND_UP(SIZE, OFPACT_ALIGNTO)
+/* Returns the ofpact following 'ofpact'. */
static inline struct ofpact *
ofpact_next(const struct ofpact *ofpact)
{
return (void *) ((uint8_t *) ofpact + OFPACT_ALIGN(ofpact->len));
}
+struct ofpact *ofpact_next_flattened(const struct ofpact *);
+
static inline struct ofpact *
ofpact_end(const struct ofpact *ofpacts, size_t ofpacts_len)
{
@@ -200,6 +203,15 @@ ofpact_end(const struct ofpact *ofpacts, size_t ofpacts_len)
#define OFPACT_FOR_EACH(POS, OFPACTS, OFPACTS_LEN) \
for ((POS) = (OFPACTS); (POS) < ofpact_end(OFPACTS, OFPACTS_LEN); \
(POS) = ofpact_next(POS))
+
+/* Assigns POS to each ofpact, in turn, in the OFPACTS_LEN bytes of ofpacts
+ * starting at OFPACTS.
+ *
+ * For ofpacts that contain nested ofpacts, this visits each of the inner
+ * ofpacts as well. */
+#define OFPACT_FOR_EACH_FLATTENED(POS, OFPACTS, OFPACTS_LEN) \
+ for ((POS) = (OFPACTS); (POS) < ofpact_end(OFPACTS, OFPACTS_LEN); \
+ (POS) = ofpact_next_flattened(POS))
/* Action structure for each OFPACT_*. */
@@ -3345,7 +3345,7 @@ ofproto_check_ofpacts(struct ofproto *ofproto,
return OFPERR_OFPMMFC_INVALID_METER;
}
- OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
+ OFPACT_FOR_EACH_FLATTENED (a, ofpacts, ofpacts_len) {
if (a->type == OFPACT_GROUP
&& !ofproto_group_exists(ofproto, ofpact_get_GROUP(a)->group_id)) {
return OFPERR_OFPBAC_BAD_OUT_GROUP;
@@ -477,7 +477,7 @@ for i in `seq 0 2`;
AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl -O OpenFlow12 -vwarn dump-group-stats br0], [0], [stdout])
AT_CHECK([STRIP_XIDS stdout | sort], [0], [dnl
- group_id=1234,ref_count=0,packet_count=3,byte_count=180,bucket0:packet_count=3,byte_count=180,bucket1:packet_count=0,byte_count=0
+ group_id=1234,ref_count=1,packet_count=3,byte_count=180,bucket0:packet_count=3,byte_count=180,bucket1:packet_count=0,byte_count=0
OFPST_GROUP reply (OF1.2):
])
OVS_VSWITCHD_STOP
@@ -498,7 +498,7 @@ for i in `seq 0 2`;
AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl -O OpenFlow12 -vwarn dump-group-stats br0], [0], [stdout])
AT_CHECK([STRIP_XIDS stdout | sort], [0], [dnl
- group_id=1234,ref_count=0,packet_count=3,byte_count=180,bucket0:packet_count=3,byte_count=180,bucket1:packet_count=3,byte_count=180
+ group_id=1234,ref_count=1,packet_count=3,byte_count=180,bucket0:packet_count=3,byte_count=180,bucket1:packet_count=3,byte_count=180
OFPST_GROUP reply (OF1.2):
])
OVS_VSWITCHD_STOP
@@ -650,6 +650,7 @@ table=8,actions=clear_actions,write_actions(output(3),output(2)),goto_table(9)
table=9,priority=20,actset_output=2 actions=12
table=9,priority=10 actions=13
])
+AT_CHECK([ovs-ofctl -O OpenFlow13 add-group br0 'group_id=5,type=all,bucket=output:1'])
AT_CHECK([ovs-ofctl -O OpenFlow13 add-flows br0 flows.txt])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [Datapath actions: 4,6,8,10,12,2
The out_port and out_group matches only looked at apply_actions instructions, but my interpretation of the OpenFlow spec is that they should also look inside write_actions. This affected the output of (and in one case the correctness of) some tests, so this updates them. Reported-by: Gavin Remaley <gavin_remaley@selinc.com> Signed-off-by: Ben Pfaff <blp@nicira.com> --- AUTHORS | 1 + lib/ofp-actions.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++-- lib/ofp-actions.h | 12 ++++++++++ ofproto/ofproto.c | 2 +- tests/ofproto-dpif.at | 5 ++-- 5 files changed, 81 insertions(+), 5 deletions(-)