2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-02 15:25:22 +00:00

ofp-actions: Add action bitmap abstraction.

Until now, sets of actions have been abstracted separately outside
ofp-actions, as enum ofputil_action_bitmap.  Drawing sets of actions into
ofp-actions, as done in this commit, makes for a better overall
abstraction of actions, with better consistency.

A big part of this commit is shifting from using ofp12_table_stats as if
it were an abstraction for OpenFlow table stats, toward using a new
struct ofputil_table_stats, which is what we generally do with other
OpenFlow structures and fits better with the rest of the code.

Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
This commit is contained in:
Ben Pfaff
2014-08-11 10:57:03 -07:00
parent 677825392c
commit 08d1e23456
11 changed files with 510 additions and 433 deletions

View File

@@ -306,12 +306,20 @@ struct ofp12_table_stats {
}; };
OFP_ASSERT(sizeof(struct ofp12_table_stats) == 128); OFP_ASSERT(sizeof(struct ofp12_table_stats) == 128);
/* Number of types of groups supported by ofp12_group_features_stats. */
#define OFPGT12_N_TYPES 4
/* Body of reply to OFPST12_GROUP_FEATURES request. Group features. */ /* Body of reply to OFPST12_GROUP_FEATURES request. Group features. */
struct ofp12_group_features_stats { struct ofp12_group_features_stats {
ovs_be32 types; /* Bitmap of OFPGT11_* values supported. */ ovs_be32 types; /* Bitmap of OFPGT11_* values supported. */
ovs_be32 capabilities; /* Bitmap of OFPGFC12_* capability supported. */ ovs_be32 capabilities; /* Bitmap of OFPGFC12_* capability supported. */
ovs_be32 max_groups[4]; /* Maximum number of groups for each type. */
ovs_be32 actions[4]; /* Bitmaps of OFPAT_* that are supported. */ /* Each element in the following arrays corresponds to the group type with
* the same number, e.g. max_groups[0] is the maximum number of OFPGT11_ALL
* groups, actions[2] is the actions supported by OFPGT11_INDIRECT
* groups. */
ovs_be32 max_groups[OFPGT12_N_TYPES]; /* Max number of groups. */
ovs_be32 actions[OFPGT12_N_TYPES]; /* Bitmaps of supported OFPAT_*. */
}; };
OFP_ASSERT(sizeof(struct ofp12_group_features_stats) == 40); OFP_ASSERT(sizeof(struct ofp12_group_features_stats) == 40);

View File

@@ -3091,6 +3091,155 @@ ofpacts_put_openflow_instructions(const struct ofpact ofpacts[],
} }
} }
/* Sets of supported actions. */
/* Two-way translation between OVS's internal "OFPACT_*" representation of
* actions and the "OFPAT_*" representation used in some OpenFlow version.
* (OFPAT_* numbering varies from one OpenFlow version to another, so a given
* instance is specific to one OpenFlow version.) */
struct ofpact_map {
enum ofpact_type ofpact; /* Internal name for action type. */
int ofpat; /* OFPAT_* number from OpenFlow spec. */
};
static const struct ofpact_map *
get_ofpact_map(enum ofp_version version)
{
/* OpenFlow 1.0 actions. */
static const struct ofpact_map of10[] = {
{ OFPACT_OUTPUT, 0 },
{ OFPACT_SET_VLAN_VID, 1 },
{ OFPACT_SET_VLAN_PCP, 2 },
{ OFPACT_STRIP_VLAN, 3 },
{ OFPACT_SET_ETH_SRC, 4 },
{ OFPACT_SET_ETH_DST, 5 },
{ OFPACT_SET_IPV4_SRC, 6 },
{ OFPACT_SET_IPV4_DST, 7 },
{ OFPACT_SET_IP_DSCP, 8 },
{ OFPACT_SET_L4_SRC_PORT, 9 },
{ OFPACT_SET_L4_DST_PORT, 10 },
{ OFPACT_ENQUEUE, 11 },
{ 0, -1 },
};
/* OpenFlow 1.1 actions. */
static const struct ofpact_map of11[] = {
{ OFPACT_OUTPUT, 0 },
{ OFPACT_SET_VLAN_VID, 1 },
{ OFPACT_SET_VLAN_PCP, 2 },
{ OFPACT_SET_ETH_SRC, 3 },
{ OFPACT_SET_ETH_DST, 4 },
{ OFPACT_SET_IPV4_SRC, 5 },
{ OFPACT_SET_IPV4_DST, 6 },
{ OFPACT_SET_IP_DSCP, 7 },
{ OFPACT_SET_IP_ECN, 8 },
{ OFPACT_SET_L4_SRC_PORT, 9 },
{ OFPACT_SET_L4_DST_PORT, 10 },
/* OFPAT_COPY_TTL_OUT (11) not supported. */
/* OFPAT_COPY_TTL_IN (12) not supported. */
{ OFPACT_SET_MPLS_LABEL, 13 },
{ OFPACT_SET_MPLS_TC, 14 },
{ OFPACT_SET_MPLS_TTL, 15 },
{ OFPACT_DEC_MPLS_TTL, 16 },
{ OFPACT_PUSH_VLAN, 17 },
{ OFPACT_STRIP_VLAN, 18 },
{ OFPACT_PUSH_MPLS, 19 },
{ OFPACT_POP_MPLS, 20 },
{ OFPACT_SET_QUEUE, 21 },
{ OFPACT_GROUP, 22 },
{ OFPACT_SET_IP_TTL, 23 },
{ OFPACT_DEC_TTL, 24 },
{ 0, -1 },
};
/* OpenFlow 1.2, 1.3, and 1.4 actions. */
static const struct ofpact_map of12[] = {
{ OFPACT_OUTPUT, 0 },
/* OFPAT_COPY_TTL_OUT (11) not supported. */
/* OFPAT_COPY_TTL_IN (12) not supported. */
{ OFPACT_SET_MPLS_TTL, 15 },
{ OFPACT_DEC_MPLS_TTL, 16 },
{ OFPACT_PUSH_VLAN, 17 },
{ OFPACT_STRIP_VLAN, 18 },
{ OFPACT_PUSH_MPLS, 19 },
{ OFPACT_POP_MPLS, 20 },
{ OFPACT_SET_QUEUE, 21 },
{ OFPACT_GROUP, 22 },
{ OFPACT_SET_IP_TTL, 23 },
{ OFPACT_DEC_TTL, 24 },
{ OFPACT_SET_FIELD, 25 },
/* OF1.3+ OFPAT_PUSH_PBB (26) not supported. */
/* OF1.3+ OFPAT_POP_PBB (27) not supported. */
{ 0, -1 },
};
switch (version) {
case OFP10_VERSION:
return of10;
case OFP11_VERSION:
return of11;
case OFP12_VERSION:
case OFP13_VERSION:
case OFP14_VERSION:
case OFP15_VERSION:
default:
return of12;
}
}
/* Converts 'ofpacts_bitmap', a bitmap whose bits correspond to OFPACT_*
* values, into a bitmap of actions suitable for OpenFlow 'version', and
* returns the result. */
ovs_be32
ofpact_bitmap_to_openflow(uint64_t ofpacts_bitmap, enum ofp_version version)
{
uint32_t openflow_bitmap = 0;
const struct ofpact_map *x;
for (x = get_ofpact_map(version); x->ofpat >= 0; x++) {
if (ofpacts_bitmap & (UINT64_C(1) << x->ofpact)) {
openflow_bitmap |= 1u << x->ofpat;
}
}
return htonl(openflow_bitmap);
}
/* Converts 'ofpat_bitmap', a bitmap of actions from an OpenFlow message with
* the given 'version' into a bitmap whose bits correspond to OFPACT_* values,
* and returns the result. */
uint64_t
ofpact_bitmap_from_openflow(ovs_be32 ofpat_bitmap, enum ofp_version version)
{
uint64_t ofpact_bitmap = 0;
const struct ofpact_map *x;
for (x = get_ofpact_map(version); x->ofpat >= 0; x++) {
if (ofpat_bitmap & htonl(1u << x->ofpat)) {
ofpact_bitmap |= UINT64_C(1) << x->ofpact;
}
}
return ofpact_bitmap;
}
/* Appends to 's' a string representation of the set of OFPACT_* represented
* by 'ofpacts_bitmap'. */
void
ofpact_bitmap_format(uint64_t ofpacts_bitmap, struct ds *s)
{
if (!ofpacts_bitmap) {
ds_put_cstr(s, "<none>");
} else {
while (ofpacts_bitmap) {
ds_put_format(s, "%s ",
ofpact_name(rightmost_1bit_idx(ofpacts_bitmap)));
ofpacts_bitmap = zero_rightmost_1bit(ofpacts_bitmap);
}
ds_chomp(s, ' ');
}
}
/* Returns true if 'action' outputs to 'port', false otherwise. */ /* Returns true if 'action' outputs to 'port', false otherwise. */
static bool static bool
ofpact_outputs_to_port(const struct ofpact *ofpact, ofp_port_t port) ofpact_outputs_to_port(const struct ofpact *ofpact, ofp_port_t port)
@@ -3648,3 +3797,14 @@ ofpact_pad(struct ofpbuf *ofpacts)
ofpbuf_put_zeros(ofpacts, pad); ofpbuf_put_zeros(ofpacts, pad);
} }
} }
const char *
ofpact_name(enum ofpact_type type)
{
switch (type) {
#define OFPACT(ENUM, STRUCT, MEMBER, NAME) case OFPACT_##ENUM: return NAME;
OFPACTS
#undef OFPACT
}
return "<unknown>";
}

View File

@@ -31,7 +31,7 @@
* This macro is used directly only internally by this header, but the list is * This macro is used directly only internally by this header, but the list is
* still of interest to developers. * still of interest to developers.
* *
* Each DEFINE_OFPACT invocation has the following parameters: * Each OFPACT invocation has the following parameters:
* *
* 1. <ENUM>, used below in the enum definition of OFPACT_<ENUM>, and * 1. <ENUM>, used below in the enum definition of OFPACT_<ENUM>, and
* elsewhere. * elsewhere.
@@ -48,81 +48,83 @@
* *
* - If "struct <STRUCT>" is variable-length, it must be the name of the * - If "struct <STRUCT>" is variable-length, it must be the name of the
* flexible array member. * flexible array member.
*
* 4. <NAME>, a quoted string that gives the name of the action, for use in
* parsing actions from text.
*/ */
#define OFPACTS \ #define OFPACTS \
/* Output. */ \ /* Output. */ \
DEFINE_OFPACT(OUTPUT, ofpact_output, ofpact) \ OFPACT(OUTPUT, ofpact_output, ofpact, "output") \
DEFINE_OFPACT(GROUP, ofpact_group, ofpact) \ OFPACT(GROUP, ofpact_group, ofpact, "group") \
DEFINE_OFPACT(CONTROLLER, ofpact_controller, ofpact) \ OFPACT(CONTROLLER, ofpact_controller, ofpact, "controller") \
DEFINE_OFPACT(ENQUEUE, ofpact_enqueue, ofpact) \ OFPACT(ENQUEUE, ofpact_enqueue, ofpact, "enqueue") \
DEFINE_OFPACT(OUTPUT_REG, ofpact_output_reg, ofpact) \ OFPACT(OUTPUT_REG, ofpact_output_reg, ofpact, "output_reg") \
DEFINE_OFPACT(BUNDLE, ofpact_bundle, slaves) \ OFPACT(BUNDLE, ofpact_bundle, slaves, "bundle") \
\ \
/* Header changes. */ \ /* Header changes. */ \
DEFINE_OFPACT(SET_FIELD, ofpact_set_field, ofpact) \ OFPACT(SET_FIELD, ofpact_set_field, ofpact, "set_field") \
DEFINE_OFPACT(SET_VLAN_VID, ofpact_vlan_vid, ofpact) \ OFPACT(SET_VLAN_VID, ofpact_vlan_vid, ofpact, "set_vlan_vid") \
DEFINE_OFPACT(SET_VLAN_PCP, ofpact_vlan_pcp, ofpact) \ OFPACT(SET_VLAN_PCP, ofpact_vlan_pcp, ofpact, "set_vlan_pcp") \
DEFINE_OFPACT(STRIP_VLAN, ofpact_null, ofpact) \ OFPACT(STRIP_VLAN, ofpact_null, ofpact, "strip_vlan") \
DEFINE_OFPACT(PUSH_VLAN, ofpact_null, ofpact) \ OFPACT(PUSH_VLAN, ofpact_null, ofpact, "push_vlan") \
DEFINE_OFPACT(SET_ETH_SRC, ofpact_mac, ofpact) \ OFPACT(SET_ETH_SRC, ofpact_mac, ofpact, "mod_dl_src") \
DEFINE_OFPACT(SET_ETH_DST, ofpact_mac, ofpact) \ OFPACT(SET_ETH_DST, ofpact_mac, ofpact, "mod_dl_dst") \
DEFINE_OFPACT(SET_IPV4_SRC, ofpact_ipv4, ofpact) \ OFPACT(SET_IPV4_SRC, ofpact_ipv4, ofpact, "mod_nw_src") \
DEFINE_OFPACT(SET_IPV4_DST, ofpact_ipv4, ofpact) \ OFPACT(SET_IPV4_DST, ofpact_ipv4, ofpact, "mod_nw_dst") \
DEFINE_OFPACT(SET_IP_DSCP, ofpact_dscp, ofpact) \ OFPACT(SET_IP_DSCP, ofpact_dscp, ofpact, "mod_nw_tos") \
DEFINE_OFPACT(SET_IP_ECN, ofpact_ecn, ofpact) \ OFPACT(SET_IP_ECN, ofpact_ecn, ofpact, "mod_nw_ecn") \
DEFINE_OFPACT(SET_IP_TTL, ofpact_ip_ttl, ofpact) \ OFPACT(SET_IP_TTL, ofpact_ip_ttl, ofpact, "mod_nw_ttl") \
DEFINE_OFPACT(SET_L4_SRC_PORT, ofpact_l4_port, ofpact) \ OFPACT(SET_L4_SRC_PORT, ofpact_l4_port, ofpact, "mod_tp_src") \
DEFINE_OFPACT(SET_L4_DST_PORT, ofpact_l4_port, ofpact) \ OFPACT(SET_L4_DST_PORT, ofpact_l4_port, ofpact, "mod_tp_dst") \
DEFINE_OFPACT(REG_MOVE, ofpact_reg_move, ofpact) \ OFPACT(REG_MOVE, ofpact_reg_move, ofpact, "move") \
DEFINE_OFPACT(REG_LOAD, ofpact_reg_load, ofpact) \ OFPACT(REG_LOAD, ofpact_reg_load, ofpact, "load") \
DEFINE_OFPACT(STACK_PUSH, ofpact_stack, ofpact) \ OFPACT(STACK_PUSH, ofpact_stack, ofpact, "push") \
DEFINE_OFPACT(STACK_POP, ofpact_stack, ofpact) \ OFPACT(STACK_POP, ofpact_stack, ofpact, "pop") \
DEFINE_OFPACT(DEC_TTL, ofpact_cnt_ids, cnt_ids) \ OFPACT(DEC_TTL, ofpact_cnt_ids, cnt_ids, "dec_ttl") \
DEFINE_OFPACT(SET_MPLS_LABEL, ofpact_mpls_label, ofpact) \ OFPACT(SET_MPLS_LABEL, ofpact_mpls_label, ofpact, "set_mpls_label") \
DEFINE_OFPACT(SET_MPLS_TC, ofpact_mpls_tc, ofpact) \ OFPACT(SET_MPLS_TC, ofpact_mpls_tc, ofpact, "set_mpls_tc") \
DEFINE_OFPACT(SET_MPLS_TTL, ofpact_mpls_ttl, ofpact) \ OFPACT(SET_MPLS_TTL, ofpact_mpls_ttl, ofpact, "set_mpls_ttl") \
DEFINE_OFPACT(DEC_MPLS_TTL, ofpact_null, ofpact) \ OFPACT(DEC_MPLS_TTL, ofpact_null, ofpact, "dec_mpls_ttl") \
DEFINE_OFPACT(PUSH_MPLS, ofpact_push_mpls, ofpact) \ OFPACT(PUSH_MPLS, ofpact_push_mpls, ofpact, "push_mpls") \
DEFINE_OFPACT(POP_MPLS, ofpact_pop_mpls, ofpact) \ OFPACT(POP_MPLS, ofpact_pop_mpls, ofpact, "pop_mpls") \
\ \
/* Metadata. */ \ /* Metadata. */ \
DEFINE_OFPACT(SET_TUNNEL, ofpact_tunnel, ofpact) \ OFPACT(SET_TUNNEL, ofpact_tunnel, ofpact, "set_tunnel") \
DEFINE_OFPACT(SET_QUEUE, ofpact_queue, ofpact) \ OFPACT(SET_QUEUE, ofpact_queue, ofpact, "set_queue") \
DEFINE_OFPACT(POP_QUEUE, ofpact_null, ofpact) \ OFPACT(POP_QUEUE, ofpact_null, ofpact, "pop_queue") \
DEFINE_OFPACT(FIN_TIMEOUT, ofpact_fin_timeout, ofpact) \ OFPACT(FIN_TIMEOUT, ofpact_fin_timeout, ofpact, "fin_timeout") \
\ \
/* Flow table interaction. */ \ /* Flow table interaction. */ \
DEFINE_OFPACT(RESUBMIT, ofpact_resubmit, ofpact) \ OFPACT(RESUBMIT, ofpact_resubmit, ofpact, "resubmit") \
DEFINE_OFPACT(LEARN, ofpact_learn, specs) \ OFPACT(LEARN, ofpact_learn, specs, "learn") \
\ \
/* Arithmetic. */ \ /* Arithmetic. */ \
DEFINE_OFPACT(MULTIPATH, ofpact_multipath, ofpact) \ OFPACT(MULTIPATH, ofpact_multipath, ofpact, "multipath") \
\ \
/* Other. */ \ /* Other. */ \
DEFINE_OFPACT(NOTE, ofpact_note, data) \ OFPACT(NOTE, ofpact_note, data, "note") \
DEFINE_OFPACT(EXIT, ofpact_null, ofpact) \ OFPACT(EXIT, ofpact_null, ofpact, "exit") \
DEFINE_OFPACT(SAMPLE, ofpact_sample, ofpact) \ OFPACT(SAMPLE, ofpact_sample, ofpact, "sample") \
\ \
/* Instructions */ \ /* Instructions. */ \
DEFINE_OFPACT(METER, ofpact_meter, ofpact) \ OFPACT(METER, ofpact_meter, ofpact, "meter") \
DEFINE_OFPACT(CLEAR_ACTIONS, ofpact_null, ofpact) \ OFPACT(CLEAR_ACTIONS, ofpact_null, ofpact, "clear_actions") \
DEFINE_OFPACT(WRITE_ACTIONS, ofpact_nest, ofpact) \ OFPACT(WRITE_ACTIONS, ofpact_nest, ofpact, "write_actions") \
DEFINE_OFPACT(WRITE_METADATA, ofpact_metadata, ofpact) \ OFPACT(WRITE_METADATA, ofpact_metadata, ofpact, "write_metadata") \
DEFINE_OFPACT(GOTO_TABLE, ofpact_goto_table, ofpact) OFPACT(GOTO_TABLE, ofpact_goto_table, ofpact, "goto_table")
/* enum ofpact_type, with a member OFPACT_<ENUM> for each action. */ /* enum ofpact_type, with a member OFPACT_<ENUM> for each action. */
enum OVS_PACKED_ENUM ofpact_type { enum OVS_PACKED_ENUM ofpact_type {
#define DEFINE_OFPACT(ENUM, STRUCT, MEMBER) OFPACT_##ENUM, #define OFPACT(ENUM, STRUCT, MEMBER, NAME) OFPACT_##ENUM,
OFPACTS OFPACTS
#undef DEFINE_OFPACT #undef OFPACT
}; };
/* N_OFPACTS, the number of values of "enum ofpact_type". */ /* Define N_OFPACTS to the number of types of ofpacts. */
enum { enum {
N_OFPACTS = #define OFPACT(ENUM, STRUCT, MEMBER, NAME) + 1
#define DEFINE_OFPACT(ENUM, STRUCT, MEMBER) + 1 N_OFPACTS = OFPACTS
OFPACTS #undef OFPACT
#undef DEFINE_OFPACT
}; };
/* Header for an action. /* Header for an action.
@@ -611,6 +613,11 @@ void ofpacts_put_openflow_instructions(const struct ofpact[],
struct ofpbuf *openflow, struct ofpbuf *openflow,
enum ofp_version ofp_version); enum ofp_version ofp_version);
/* Sets of supported actions. */
ovs_be32 ofpact_bitmap_to_openflow(uint64_t ofpacts_bitmap, enum ofp_version);
uint64_t ofpact_bitmap_from_openflow(ovs_be32 ofpat_bitmap, enum ofp_version);
void ofpact_bitmap_format(uint64_t ofpacts_bitmap, struct ds *);
/* Working with ofpacts. */ /* Working with ofpacts. */
bool ofpacts_output_to_port(const struct ofpact[], size_t ofpacts_len, bool ofpacts_output_to_port(const struct ofpact[], size_t ofpacts_len,
ofp_port_t port); ofp_port_t port);
@@ -624,6 +631,7 @@ uint32_t ofpacts_get_meter(const struct ofpact[], size_t ofpacts_len);
* *
* (For parsing ofpacts, see ofp-parse.h.) */ * (For parsing ofpacts, see ofp-parse.h.) */
void ofpacts_format(const struct ofpact[], size_t ofpacts_len, struct ds *); void ofpacts_format(const struct ofpact[], size_t ofpacts_len, struct ds *);
const char *ofpact_name(enum ofpact_type);
/* Internal use by the helpers below. */ /* Internal use by the helpers below. */
void ofpact_init(struct ofpact *, enum ofpact_type, size_t len); void ofpact_init(struct ofpact *, enum ofpact_type, size_t len);
@@ -667,7 +675,7 @@ void *ofpact_put(struct ofpbuf *, enum ofpact_type, size_t len);
* An integer constant, the value of OFPACT_<ENUM>_RAW_SIZE rounded up to a * An integer constant, the value of OFPACT_<ENUM>_RAW_SIZE rounded up to a
* multiple of OFPACT_ALIGNTO. * multiple of OFPACT_ALIGNTO.
*/ */
#define DEFINE_OFPACT(ENUM, STRUCT, MEMBER) \ #define OFPACT(ENUM, STRUCT, MEMBER, NAME) \
BUILD_ASSERT_DECL(offsetof(struct STRUCT, ofpact) == 0); \ BUILD_ASSERT_DECL(offsetof(struct STRUCT, ofpact) == 0); \
\ \
enum { OFPACT_##ENUM##_RAW_SIZE \ enum { OFPACT_##ENUM##_RAW_SIZE \
@@ -699,7 +707,7 @@ void *ofpact_put(struct ofpbuf *, enum ofpact_type, size_t len);
OFPACT_##ENUM##_RAW_SIZE); \ OFPACT_##ENUM##_RAW_SIZE); \
} }
OFPACTS OFPACTS
#undef DEFINE_OFPACT #undef OFPACT
/* Functions to use after adding ofpacts to a buffer. */ /* Functions to use after adding ofpacts to a buffer. */
void ofpact_update_len(struct ofpbuf *, struct ofpact *); void ofpact_update_len(struct ofpbuf *, struct ofpact *);

View File

@@ -467,45 +467,6 @@ ofputil_capabilities_to_name(uint32_t bit)
return NULL; return NULL;
} }
static const char *
ofputil_action_bitmap_to_name(uint32_t bit)
{
enum ofputil_action_bitmap action = bit;
switch (action) {
case OFPUTIL_A_OUTPUT: return "OUTPUT";
case OFPUTIL_A_SET_VLAN_VID: return "SET_VLAN_VID";
case OFPUTIL_A_SET_VLAN_PCP: return "SET_VLAN_PCP";
case OFPUTIL_A_STRIP_VLAN: return "STRIP_VLAN";
case OFPUTIL_A_SET_DL_SRC: return "SET_DL_SRC";
case OFPUTIL_A_SET_DL_DST: return "SET_DL_DST";
case OFPUTIL_A_SET_NW_SRC: return "SET_NW_SRC";
case OFPUTIL_A_SET_NW_DST: return "SET_NW_DST";
case OFPUTIL_A_SET_NW_ECN: return "SET_NW_ECN";
case OFPUTIL_A_SET_NW_TOS: return "SET_NW_TOS";
case OFPUTIL_A_SET_TP_SRC: return "SET_TP_SRC";
case OFPUTIL_A_SET_TP_DST: return "SET_TP_DST";
case OFPUTIL_A_SET_FIELD: return "SET_FIELD";
case OFPUTIL_A_ENQUEUE: return "ENQUEUE";
case OFPUTIL_A_COPY_TTL_OUT: return "COPY_TTL_OUT";
case OFPUTIL_A_COPY_TTL_IN: return "COPY_TTL_IN";
case OFPUTIL_A_SET_MPLS_LABEL: return "SET_MPLS_LABEL";
case OFPUTIL_A_SET_MPLS_TC: return "SET_MPLS_TC";
case OFPUTIL_A_SET_MPLS_TTL: return "SET_MPLS_TTL";
case OFPUTIL_A_DEC_MPLS_TTL: return "DEC_MPLS_TTL";
case OFPUTIL_A_PUSH_VLAN: return "PUSH_VLAN";
case OFPUTIL_A_POP_VLAN: return "POP_VLAN";
case OFPUTIL_A_PUSH_MPLS: return "PUSH_MPLS";
case OFPUTIL_A_POP_MPLS: return "POP_MPLS";
case OFPUTIL_A_SET_QUEUE: return "SET_QUEUE";
case OFPUTIL_A_GROUP: return "GROUP";
case OFPUTIL_A_SET_NW_TTL: return "SET_NW_TTL";
case OFPUTIL_A_DEC_NW_TTL: return "DEC_NW_TTL";
}
return NULL;
}
static void static void
ofp_print_switch_features(struct ds *string, const struct ofp_header *oh) ofp_print_switch_features(struct ds *string, const struct ofp_header *oh)
{ {
@@ -536,8 +497,7 @@ ofp_print_switch_features(struct ds *string, const struct ofp_header *oh)
switch ((enum ofp_version)oh->version) { switch ((enum ofp_version)oh->version) {
case OFP10_VERSION: case OFP10_VERSION:
ds_put_cstr(string, "actions: "); ds_put_cstr(string, "actions: ");
ofp_print_bit_names(string, features.actions, ofpact_bitmap_format(features.ofpacts, string);
ofputil_action_bitmap_to_name, ' ');
ds_put_char(string, '\n'); ds_put_char(string, '\n');
break; break;
case OFP11_VERSION: case OFP11_VERSION:
@@ -2458,10 +2418,23 @@ ofp_print_group_stats(struct ds *s, const struct ofp_header *oh)
} }
} }
static const char *
group_type_to_string(enum ofp11_group_type type)
{
switch (type) {
case OFPGT11_ALL: return "all";
case OFPGT11_SELECT: return "select";
case OFPGT11_INDIRECT: return "indirect";
case OFPGT11_FF: return "fast failover";
default: OVS_NOT_REACHED();
}
}
static void static void
ofp_print_group_features(struct ds *string, const struct ofp_header *oh) ofp_print_group_features(struct ds *string, const struct ofp_header *oh)
{ {
struct ofputil_group_features features; struct ofputil_group_features features;
int i;
ofputil_decode_group_features_reply(oh, &features); ofputil_decode_group_features_reply(oh, &features);
@@ -2470,32 +2443,15 @@ ofp_print_group_features(struct ds *string, const struct ofp_header *oh)
ds_put_format(string, " Capabilities: 0x%"PRIx32"\n", ds_put_format(string, " Capabilities: 0x%"PRIx32"\n",
features.capabilities); features.capabilities);
if (features.types & (1u << OFPGT11_ALL)) { for (i = 0; i < OFPGT12_N_TYPES; i++) {
ds_put_format(string, " All group :\n"); if (features.types & (1u << i)) {
ds_put_format(string, ds_put_format(string, " %s group:\n", group_type_to_string(i));
" max_groups = %#"PRIx32" actions=0x%08"PRIx32"\n", ds_put_format(string, " max_groups=%#"PRIx32"\n",
features.max_groups[0], features.actions[0]); features.max_groups[i]);
} ds_put_format(string, " actions: ");
ofpact_bitmap_format(features.ofpacts[i], string);
if (features.types & (1u << OFPGT11_SELECT)) { ds_put_char(string, '\n');
ds_put_format(string, " Select group :\n"); }
ds_put_format(string, " max_groups = %#"PRIx32" "
"actions=0x%08"PRIx32"\n",
features.max_groups[1], features.actions[1]);
}
if (features.types & (1u << OFPGT11_INDIRECT)) {
ds_put_format(string, " Indirect group :\n");
ds_put_format(string, " max_groups = %#"PRIx32" "
"actions=0x%08"PRIx32"\n",
features.max_groups[2], features.actions[2]);
}
if (features.types & (1u << OFPGT11_FF)) {
ds_put_format(string, " Fast Failover group :\n");
ds_put_format(string, " max_groups = %#"PRIx32" "
"actions=0x%08"PRIx32"\n",
features.max_groups[3], features.actions[3]);
} }
} }
@@ -2535,23 +2491,12 @@ ofp_print_group_mod(struct ds *s, const struct ofp_header *oh)
ofp_print_group(s, gm.group_id, gm.type, &gm.buckets); ofp_print_group(s, gm.group_id, gm.type, &gm.buckets);
} }
static const char *
ofp13_action_to_string(uint32_t bit)
{
switch (bit) {
#define OFPAT13_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
case 1u << ENUM: return NAME;
#include "ofp-util.def"
}
return NULL;
}
static void static void
print_table_action_features(struct ds *s, print_table_action_features(struct ds *s,
const struct ofputil_table_action_features *taf) const struct ofputil_table_action_features *taf)
{ {
ds_put_cstr(s, " actions: "); ds_put_cstr(s, " actions: ");
ofp_print_bit_names(s, taf->actions, ofp13_action_to_string, ','); ofpact_bitmap_format(taf->ofpacts, s);
ds_put_char(s, '\n'); ds_put_char(s, '\n');
ds_put_cstr(s, " supported on Set-Field: "); ds_put_cstr(s, " supported on Set-Field: ");
@@ -2572,7 +2517,7 @@ static bool
table_action_features_equal(const struct ofputil_table_action_features *a, table_action_features_equal(const struct ofputil_table_action_features *a,
const struct ofputil_table_action_features *b) const struct ofputil_table_action_features *b)
{ {
return (a->actions == b->actions return (a->ofpacts == b->ofpacts
&& bitmap_equal(a->set_fields.bm, b->set_fields.bm, MFF_N_IDS)); && bitmap_equal(a->set_fields.bm, b->set_fields.bm, MFF_N_IDS));
} }

View File

@@ -4012,42 +4012,6 @@ BUILD_ASSERT_DECL((int) OFPUTIL_C_IP_REASM == OFPC_IP_REASM);
BUILD_ASSERT_DECL((int) OFPUTIL_C_QUEUE_STATS == OFPC_QUEUE_STATS); BUILD_ASSERT_DECL((int) OFPUTIL_C_QUEUE_STATS == OFPC_QUEUE_STATS);
BUILD_ASSERT_DECL((int) OFPUTIL_C_ARP_MATCH_IP == OFPC_ARP_MATCH_IP); BUILD_ASSERT_DECL((int) OFPUTIL_C_ARP_MATCH_IP == OFPC_ARP_MATCH_IP);
struct ofputil_action_bit_translation {
enum ofputil_action_bitmap ofputil_bit;
int of_bit;
};
static const struct ofputil_action_bit_translation of10_action_bits[] = {
{ OFPUTIL_A_OUTPUT, OFPAT10_OUTPUT },
{ OFPUTIL_A_SET_VLAN_VID, OFPAT10_SET_VLAN_VID },
{ OFPUTIL_A_SET_VLAN_PCP, OFPAT10_SET_VLAN_PCP },
{ OFPUTIL_A_STRIP_VLAN, OFPAT10_STRIP_VLAN },
{ OFPUTIL_A_SET_DL_SRC, OFPAT10_SET_DL_SRC },
{ OFPUTIL_A_SET_DL_DST, OFPAT10_SET_DL_DST },
{ OFPUTIL_A_SET_NW_SRC, OFPAT10_SET_NW_SRC },
{ OFPUTIL_A_SET_NW_DST, OFPAT10_SET_NW_DST },
{ OFPUTIL_A_SET_NW_TOS, OFPAT10_SET_NW_TOS },
{ OFPUTIL_A_SET_TP_SRC, OFPAT10_SET_TP_SRC },
{ OFPUTIL_A_SET_TP_DST, OFPAT10_SET_TP_DST },
{ OFPUTIL_A_ENQUEUE, OFPAT10_ENQUEUE },
{ 0, 0 },
};
static enum ofputil_action_bitmap
decode_action_bits(ovs_be32 of_actions,
const struct ofputil_action_bit_translation *x)
{
enum ofputil_action_bitmap ofputil_actions;
ofputil_actions = 0;
for (; x->ofputil_bit; x++) {
if (of_actions & htonl(1u << x->of_bit)) {
ofputil_actions |= x->ofputil_bit;
}
}
return ofputil_actions;
}
static uint32_t static uint32_t
ofputil_capabilities_mask(enum ofp_version ofp_version) ofputil_capabilities_mask(enum ofp_version ofp_version)
{ {
@@ -4096,13 +4060,14 @@ ofputil_decode_switch_features(const struct ofp_header *oh,
if (osf->capabilities & htonl(OFPC10_STP)) { if (osf->capabilities & htonl(OFPC10_STP)) {
features->capabilities |= OFPUTIL_C_STP; features->capabilities |= OFPUTIL_C_STP;
} }
features->actions = decode_action_bits(osf->actions, of10_action_bits); features->ofpacts = ofpact_bitmap_from_openflow(osf->actions,
OFP10_VERSION);
} else if (raw == OFPRAW_OFPT11_FEATURES_REPLY } else if (raw == OFPRAW_OFPT11_FEATURES_REPLY
|| raw == OFPRAW_OFPT13_FEATURES_REPLY) { || raw == OFPRAW_OFPT13_FEATURES_REPLY) {
if (osf->capabilities & htonl(OFPC11_GROUP_STATS)) { if (osf->capabilities & htonl(OFPC11_GROUP_STATS)) {
features->capabilities |= OFPUTIL_C_GROUP_STATS; features->capabilities |= OFPUTIL_C_GROUP_STATS;
} }
features->actions = 0; features->ofpacts = 0;
if (raw == OFPRAW_OFPT13_FEATURES_REPLY) { if (raw == OFPRAW_OFPT13_FEATURES_REPLY) {
features->auxiliary_id = osf->auxiliary_id; features->auxiliary_id = osf->auxiliary_id;
} }
@@ -4153,21 +4118,6 @@ ofputil_switch_features_has_ports(struct ofpbuf *b)
return false; return false;
} }
static ovs_be32
encode_action_bits(enum ofputil_action_bitmap ofputil_actions,
const struct ofputil_action_bit_translation *x)
{
uint32_t of_actions;
of_actions = 0;
for (; x->ofputil_bit; x++) {
if (ofputil_actions & x->ofputil_bit) {
of_actions |= 1 << x->of_bit;
}
}
return htonl(of_actions);
}
/* Returns a buffer owned by the caller that encodes 'features' in the format /* Returns a buffer owned by the caller that encodes 'features' in the format
* required by 'protocol' with the given 'xid'. The caller should append port * required by 'protocol' with the given 'xid'. The caller should append port
* information to the buffer with subsequent calls to * information to the buffer with subsequent calls to
@@ -4212,7 +4162,8 @@ ofputil_encode_switch_features(const struct ofputil_switch_features *features,
if (features->capabilities & OFPUTIL_C_STP) { if (features->capabilities & OFPUTIL_C_STP) {
osf->capabilities |= htonl(OFPC10_STP); osf->capabilities |= htonl(OFPC10_STP);
} }
osf->actions = encode_action_bits(features->actions, of10_action_bits); osf->actions = ofpact_bitmap_to_openflow(features->ofpacts,
OFP10_VERSION);
break; break;
case OFP13_VERSION: case OFP13_VERSION:
case OFP14_VERSION: case OFP14_VERSION:
@@ -4504,20 +4455,25 @@ pull_table_feature_property(struct ofpbuf *msg, struct ofpbuf *payload,
} }
static enum ofperr static enum ofperr
parse_table_ids(struct ofpbuf *payload, uint32_t *ids) parse_action_bitmap(struct ofpbuf *payload, enum ofp_version ofp_version,
uint64_t *ofpacts)
{ {
uint16_t type; uint32_t types = 0;
*ids = 0;
while (ofpbuf_size(payload) > 0) { while (ofpbuf_size(payload) > 0) {
enum ofperr error = pull_table_feature_property(payload, NULL, &type); uint16_t type;
enum ofperr error;
error = pull_table_feature_property(payload, NULL, &type);
if (error) { if (error) {
return error; return error;
} }
if (type < CHAR_BIT * sizeof *ids) { if (type < CHAR_BIT * sizeof types) {
*ids |= 1u << type; types |= 1u << type;
} }
} }
*ofpacts = ofpact_bitmap_from_openflow(htonl(types), ofp_version);
return 0; return 0;
} }
@@ -4646,12 +4602,14 @@ int
ofputil_decode_table_features(struct ofpbuf *msg, ofputil_decode_table_features(struct ofpbuf *msg,
struct ofputil_table_features *tf, bool loose) struct ofputil_table_features *tf, bool loose)
{ {
const struct ofp_header *oh;
struct ofp13_table_features *otf; struct ofp13_table_features *otf;
unsigned int len; unsigned int len;
if (!msg->frame) { if (!msg->frame) {
ofpraw_pull_assert(msg); ofpraw_pull_assert(msg);
} }
oh = ofpbuf_l2(msg);
if (!ofpbuf_size(msg)) { if (!ofpbuf_size(msg)) {
return EOF; return EOF;
@@ -4708,17 +4666,21 @@ ofputil_decode_table_features(struct ofpbuf *msg,
break; break;
case OFPTFPT13_WRITE_ACTIONS: case OFPTFPT13_WRITE_ACTIONS:
error = parse_table_ids(&payload, &tf->nonmiss.write.actions); error = parse_action_bitmap(&payload, oh->version,
&tf->nonmiss.write.ofpacts);
break; break;
case OFPTFPT13_WRITE_ACTIONS_MISS: case OFPTFPT13_WRITE_ACTIONS_MISS:
error = parse_table_ids(&payload, &tf->miss.write.actions); error = parse_action_bitmap(&payload, oh->version,
&tf->miss.write.ofpacts);
break; break;
case OFPTFPT13_APPLY_ACTIONS: case OFPTFPT13_APPLY_ACTIONS:
error = parse_table_ids(&payload, &tf->nonmiss.apply.actions); error = parse_action_bitmap(&payload, oh->version,
&tf->nonmiss.apply.ofpacts);
break; break;
case OFPTFPT13_APPLY_ACTIONS_MISS: case OFPTFPT13_APPLY_ACTIONS_MISS:
error = parse_table_ids(&payload, &tf->miss.apply.actions); error = parse_action_bitmap(&payload, oh->version,
&tf->miss.apply.ofpacts);
break; break;
case OFPTFPT13_MATCH: case OFPTFPT13_MATCH:
@@ -5030,27 +4992,27 @@ ofputil_decode_role_status(const struct ofp_header *oh,
/* Table stats. */ /* Table stats. */
static void static void
ofputil_put_ofp10_table_stats(const struct ofp12_table_stats *in, ofputil_put_ofp10_table_stats(const struct ofputil_table_stats *in,
struct ofpbuf *buf) struct ofpbuf *buf)
{ {
struct wc_map { struct wc_map {
enum ofp10_flow_wildcards wc10; enum ofp10_flow_wildcards wc10;
enum oxm12_ofb_match_fields mf12; enum mf_field_id mf;
}; };
static const struct wc_map wc_map[] = { static const struct wc_map wc_map[] = {
{ OFPFW10_IN_PORT, OFPXMT12_OFB_IN_PORT }, { OFPFW10_IN_PORT, MFF_IN_PORT },
{ OFPFW10_DL_VLAN, OFPXMT12_OFB_VLAN_VID }, { OFPFW10_DL_VLAN, MFF_VLAN_VID },
{ OFPFW10_DL_SRC, OFPXMT12_OFB_ETH_SRC }, { OFPFW10_DL_SRC, MFF_ETH_SRC },
{ OFPFW10_DL_DST, OFPXMT12_OFB_ETH_DST}, { OFPFW10_DL_DST, MFF_ETH_DST},
{ OFPFW10_DL_TYPE, OFPXMT12_OFB_ETH_TYPE }, { OFPFW10_DL_TYPE, MFF_ETH_TYPE },
{ OFPFW10_NW_PROTO, OFPXMT12_OFB_IP_PROTO }, { OFPFW10_NW_PROTO, MFF_IP_PROTO },
{ OFPFW10_TP_SRC, OFPXMT12_OFB_TCP_SRC }, { OFPFW10_TP_SRC, MFF_TCP_SRC },
{ OFPFW10_TP_DST, OFPXMT12_OFB_TCP_DST }, { OFPFW10_TP_DST, MFF_TCP_DST },
{ OFPFW10_NW_SRC_MASK, OFPXMT12_OFB_IPV4_SRC }, { OFPFW10_NW_SRC_MASK, MFF_IPV4_SRC },
{ OFPFW10_NW_DST_MASK, OFPXMT12_OFB_IPV4_DST }, { OFPFW10_NW_DST_MASK, MFF_IPV4_DST },
{ OFPFW10_DL_VLAN_PCP, OFPXMT12_OFB_VLAN_PCP }, { OFPFW10_DL_VLAN_PCP, MFF_VLAN_PCP },
{ OFPFW10_NW_TOS, OFPXMT12_OFB_IP_DSCP }, { OFPFW10_NW_TOS, MFF_IP_DSCP },
}; };
struct ofp10_table_stats *out; struct ofp10_table_stats *out;
@@ -5061,41 +5023,41 @@ ofputil_put_ofp10_table_stats(const struct ofp12_table_stats *in,
ovs_strlcpy(out->name, in->name, sizeof out->name); ovs_strlcpy(out->name, in->name, sizeof out->name);
out->wildcards = 0; out->wildcards = 0;
for (p = wc_map; p < &wc_map[ARRAY_SIZE(wc_map)]; p++) { for (p = wc_map; p < &wc_map[ARRAY_SIZE(wc_map)]; p++) {
if (in->wildcards & htonll(1ULL << p->mf12)) { if (bitmap_is_set(in->wildcards.bm, p->mf)) {
out->wildcards |= htonl(p->wc10); out->wildcards |= htonl(p->wc10);
} }
} }
out->max_entries = in->max_entries; out->max_entries = htonl(in->max_entries);
out->active_count = in->active_count; out->active_count = htonl(in->active_count);
put_32aligned_be64(&out->lookup_count, in->lookup_count); put_32aligned_be64(&out->lookup_count, htonll(in->lookup_count));
put_32aligned_be64(&out->matched_count, in->matched_count); put_32aligned_be64(&out->matched_count, htonll(in->matched_count));
} }
static ovs_be32 static ovs_be32
oxm12_to_ofp11_flow_match_fields(ovs_be64 oxm12) fields_to_ofp11_flow_match_fields(const struct mf_bitmap *fields)
{ {
struct map { struct map {
enum ofp11_flow_match_fields fmf11; enum ofp11_flow_match_fields fmf11;
enum oxm12_ofb_match_fields mf12; enum mf_field_id mf;
}; };
static const struct map map[] = { static const struct map map[] = {
{ OFPFMF11_IN_PORT, OFPXMT12_OFB_IN_PORT }, { OFPFMF11_IN_PORT, MFF_IN_PORT },
{ OFPFMF11_DL_VLAN, OFPXMT12_OFB_VLAN_VID }, { OFPFMF11_DL_VLAN, MFF_VLAN_VID },
{ OFPFMF11_DL_VLAN_PCP, OFPXMT12_OFB_VLAN_PCP }, { OFPFMF11_DL_VLAN_PCP, MFF_VLAN_PCP },
{ OFPFMF11_DL_TYPE, OFPXMT12_OFB_ETH_TYPE }, { OFPFMF11_DL_TYPE, MFF_ETH_TYPE },
{ OFPFMF11_NW_TOS, OFPXMT12_OFB_IP_DSCP }, { OFPFMF11_NW_TOS, MFF_IP_DSCP },
{ OFPFMF11_NW_PROTO, OFPXMT12_OFB_IP_PROTO }, { OFPFMF11_NW_PROTO, MFF_IP_PROTO },
{ OFPFMF11_TP_SRC, OFPXMT12_OFB_TCP_SRC }, { OFPFMF11_TP_SRC, MFF_TCP_SRC },
{ OFPFMF11_TP_DST, OFPXMT12_OFB_TCP_DST }, { OFPFMF11_TP_DST, MFF_TCP_DST },
{ OFPFMF11_MPLS_LABEL, OFPXMT12_OFB_MPLS_LABEL }, { OFPFMF11_MPLS_LABEL, MFF_MPLS_LABEL },
{ OFPFMF11_MPLS_TC, OFPXMT12_OFB_MPLS_TC }, { OFPFMF11_MPLS_TC, MFF_MPLS_TC },
/* I don't know what OFPFMF11_TYPE means. */ /* I don't know what OFPFMF11_TYPE means. */
{ OFPFMF11_DL_SRC, OFPXMT12_OFB_ETH_SRC }, { OFPFMF11_DL_SRC, MFF_ETH_SRC },
{ OFPFMF11_DL_DST, OFPXMT12_OFB_ETH_DST }, { OFPFMF11_DL_DST, MFF_ETH_DST },
{ OFPFMF11_NW_SRC, OFPXMT12_OFB_IPV4_SRC }, { OFPFMF11_NW_SRC, MFF_IPV4_SRC },
{ OFPFMF11_NW_DST, OFPXMT12_OFB_IPV4_DST }, { OFPFMF11_NW_DST, MFF_IPV4_DST },
{ OFPFMF11_METADATA, OFPXMT12_OFB_METADATA }, { OFPFMF11_METADATA, MFF_METADATA },
}; };
const struct map *p; const struct map *p;
@@ -5103,7 +5065,7 @@ oxm12_to_ofp11_flow_match_fields(ovs_be64 oxm12)
fmf11 = 0; fmf11 = 0;
for (p = map; p < &map[ARRAY_SIZE(map)]; p++) { for (p = map; p < &map[ARRAY_SIZE(map)]; p++) {
if (oxm12 & htonll(1ULL << p->mf12)) { if (bitmap_is_set(fields->bm, p->mf)) {
fmf11 |= p->fmf11; fmf11 |= p->fmf11;
} }
} }
@@ -5111,7 +5073,7 @@ oxm12_to_ofp11_flow_match_fields(ovs_be64 oxm12)
} }
static void static void
ofputil_put_ofp11_table_stats(const struct ofp12_table_stats *in, ofputil_put_ofp11_table_stats(const struct ofputil_table_stats *in,
struct ofpbuf *buf) struct ofpbuf *buf)
{ {
struct ofp11_table_stats *out; struct ofp11_table_stats *out;
@@ -5119,50 +5081,84 @@ ofputil_put_ofp11_table_stats(const struct ofp12_table_stats *in,
out = ofpbuf_put_zeros(buf, sizeof *out); out = ofpbuf_put_zeros(buf, sizeof *out);
out->table_id = in->table_id; out->table_id = in->table_id;
ovs_strlcpy(out->name, in->name, sizeof out->name); ovs_strlcpy(out->name, in->name, sizeof out->name);
out->wildcards = oxm12_to_ofp11_flow_match_fields(in->wildcards); out->wildcards = fields_to_ofp11_flow_match_fields(&in->wildcards);
out->match = oxm12_to_ofp11_flow_match_fields(in->match); out->match = fields_to_ofp11_flow_match_fields(&in->match);
out->instructions = in->instructions; out->instructions = htonl(in->instructions);
out->write_actions = in->write_actions; out->write_actions = ofpact_bitmap_to_openflow(in->write_ofpacts,
out->apply_actions = in->apply_actions; OFP11_VERSION);
out->config = in->config; out->apply_actions = ofpact_bitmap_to_openflow(in->apply_ofpacts,
out->max_entries = in->max_entries; OFP11_VERSION);
out->active_count = in->active_count; out->config = htonl(in->config);
out->lookup_count = in->lookup_count; out->max_entries = htonl(in->max_entries);
out->matched_count = in->matched_count; out->active_count = htonl(in->active_count);
out->lookup_count = htonll(in->lookup_count);
out->matched_count = htonll(in->matched_count);
}
static ovs_be64
mf_bitmap_to_oxm_bitmap(const struct mf_bitmap *fields,
enum ofp_version version)
{
uint64_t oxm_bitmap = 0;
int i;
BITMAP_FOR_EACH_1 (i, MFF_N_IDS, fields->bm) {
uint32_t oxm = mf_oxm_header(i, version);
uint32_t vendor = NXM_VENDOR(oxm);
int field = NXM_FIELD(oxm);
if (vendor == OFPXMC12_OPENFLOW_BASIC && field < 64) {
oxm_bitmap |= UINT64_C(1) << field;
}
}
return htonll(oxm_bitmap);
} }
static void static void
ofputil_put_ofp12_table_stats(const struct ofp12_table_stats *in, ofputil_put_ofp12_table_stats(const struct ofputil_table_stats *in,
struct ofpbuf *buf) struct ofpbuf *buf)
{ {
struct ofp12_table_stats *out = ofpbuf_put(buf, in, sizeof *in); struct ofp12_table_stats *out;
/* Trim off OF1.3-only capabilities. */ out = ofpbuf_put_zeros(buf, sizeof *out);
out->match &= htonll(OFPXMT12_MASK); out->table_id = in->table_id;
out->wildcards &= htonll(OFPXMT12_MASK); ovs_strlcpy(out->name, in->name, sizeof out->name);
out->write_setfields &= htonll(OFPXMT12_MASK); out->match = mf_bitmap_to_oxm_bitmap(&in->match, OFP12_VERSION);
out->apply_setfields &= htonll(OFPXMT12_MASK); out->wildcards = mf_bitmap_to_oxm_bitmap(&in->wildcards, OFP12_VERSION);
out->write_actions = ofpact_bitmap_to_openflow(in->write_ofpacts,
OFP12_VERSION);
out->apply_actions = ofpact_bitmap_to_openflow(in->apply_ofpacts,
OFP12_VERSION);
out->write_setfields = mf_bitmap_to_oxm_bitmap(&in->write_setfields,
OFP12_VERSION);
out->apply_setfields = mf_bitmap_to_oxm_bitmap(&in->apply_setfields,
OFP12_VERSION);
out->metadata_match = in->metadata_match;
out->metadata_write = in->metadata_write;
out->instructions = htonl(in->instructions & OFPIT11_ALL);
out->config = htonl(in->config);
out->max_entries = htonl(in->max_entries);
out->active_count = htonl(in->active_count);
out->lookup_count = htonll(in->lookup_count);
out->matched_count = htonll(in->matched_count);
} }
static void static void
ofputil_put_ofp13_table_stats(const struct ofp12_table_stats *in, ofputil_put_ofp13_table_stats(const struct ofputil_table_stats *in,
struct ofpbuf *buf) struct ofpbuf *buf)
{ {
struct ofp13_table_stats *out; struct ofp13_table_stats *out;
/* OF 1.3 splits table features off the ofp_table_stats,
* so there is not much here. */
out = ofpbuf_put_uninit(buf, sizeof *out); out = ofpbuf_put_uninit(buf, sizeof *out);
out->table_id = in->table_id; out->table_id = in->table_id;
out->active_count = in->active_count; out->active_count = htonl(in->active_count);
out->lookup_count = in->lookup_count; out->lookup_count = htonll(in->lookup_count);
out->matched_count = in->matched_count; out->matched_count = htonll(in->matched_count);
} }
struct ofpbuf * struct ofpbuf *
ofputil_encode_table_stats_reply(const struct ofp12_table_stats stats[], int n, ofputil_encode_table_stats_reply(const struct ofputil_table_stats stats[],
const struct ofp_header *request) int n, const struct ofp_header *request)
{ {
struct ofpbuf *reply; struct ofpbuf *reply;
int i; int i;
@@ -6796,20 +6792,18 @@ ofputil_encode_group_features_reply(
{ {
struct ofp12_group_features_stats *ogf; struct ofp12_group_features_stats *ogf;
struct ofpbuf *reply; struct ofpbuf *reply;
int i;
reply = ofpraw_alloc_xid(OFPRAW_OFPST12_GROUP_FEATURES_REPLY, reply = ofpraw_alloc_xid(OFPRAW_OFPST12_GROUP_FEATURES_REPLY,
request->version, request->xid, 0); request->version, request->xid, 0);
ogf = ofpbuf_put_zeros(reply, sizeof *ogf); ogf = ofpbuf_put_zeros(reply, sizeof *ogf);
ogf->types = htonl(features->types); ogf->types = htonl(features->types);
ogf->capabilities = htonl(features->capabilities); ogf->capabilities = htonl(features->capabilities);
ogf->max_groups[0] = htonl(features->max_groups[0]); for (i = 0; i < OFPGT12_N_TYPES; i++) {
ogf->max_groups[1] = htonl(features->max_groups[1]); ogf->max_groups[i] = htonl(features->max_groups[i]);
ogf->max_groups[2] = htonl(features->max_groups[2]); ogf->actions[i] = ofpact_bitmap_to_openflow(features->ofpacts[i],
ogf->max_groups[3] = htonl(features->max_groups[3]); request->version);
ogf->actions[0] = htonl(features->actions[0]); }
ogf->actions[1] = htonl(features->actions[1]);
ogf->actions[2] = htonl(features->actions[2]);
ogf->actions[3] = htonl(features->actions[3]);
return reply; return reply;
} }
@@ -6820,17 +6814,15 @@ ofputil_decode_group_features_reply(const struct ofp_header *oh,
struct ofputil_group_features *features) struct ofputil_group_features *features)
{ {
const struct ofp12_group_features_stats *ogf = ofpmsg_body(oh); const struct ofp12_group_features_stats *ogf = ofpmsg_body(oh);
int i;
features->types = ntohl(ogf->types); features->types = ntohl(ogf->types);
features->capabilities = ntohl(ogf->capabilities); features->capabilities = ntohl(ogf->capabilities);
features->max_groups[0] = ntohl(ogf->max_groups[0]); for (i = 0; i < OFPGT12_N_TYPES; i++) {
features->max_groups[1] = ntohl(ogf->max_groups[1]); features->max_groups[i] = ntohl(ogf->max_groups[i]);
features->max_groups[2] = ntohl(ogf->max_groups[2]); features->ofpacts[i] = ofpact_bitmap_from_openflow(
features->max_groups[3] = ntohl(ogf->max_groups[3]); ogf->actions[i], oh->version);
features->actions[0] = ntohl(ogf->actions[0]); }
features->actions[1] = ntohl(ogf->actions[1]);
features->actions[2] = ntohl(ogf->actions[2]);
features->actions[3] = ntohl(ogf->actions[3]);
} }
/* Parse a group status request message into a 32 bit OpenFlow 1.1 /* Parse a group status request message into a 32 bit OpenFlow 1.1

View File

@@ -528,37 +528,6 @@ enum ofputil_capabilities {
OFPUTIL_C_PORT_BLOCKED = 1 << 8, /* Switch will block looping ports */ OFPUTIL_C_PORT_BLOCKED = 1 << 8, /* Switch will block looping ports */
}; };
enum ofputil_action_bitmap {
OFPUTIL_A_OUTPUT = 1 << 0,
OFPUTIL_A_SET_VLAN_VID = 1 << 1,
OFPUTIL_A_SET_VLAN_PCP = 1 << 2,
OFPUTIL_A_STRIP_VLAN = 1 << 3,
OFPUTIL_A_SET_DL_SRC = 1 << 4,
OFPUTIL_A_SET_DL_DST = 1 << 5,
OFPUTIL_A_SET_NW_SRC = 1 << 6,
OFPUTIL_A_SET_NW_DST = 1 << 7,
OFPUTIL_A_SET_NW_ECN = 1 << 8,
OFPUTIL_A_SET_NW_TOS = 1 << 9,
OFPUTIL_A_SET_TP_SRC = 1 << 10,
OFPUTIL_A_SET_TP_DST = 1 << 11,
OFPUTIL_A_ENQUEUE = 1 << 12,
OFPUTIL_A_COPY_TTL_OUT = 1 << 13,
OFPUTIL_A_COPY_TTL_IN = 1 << 14,
OFPUTIL_A_SET_MPLS_LABEL = 1 << 15,
OFPUTIL_A_SET_MPLS_TC = 1 << 16,
OFPUTIL_A_SET_MPLS_TTL = 1 << 17,
OFPUTIL_A_DEC_MPLS_TTL = 1 << 18,
OFPUTIL_A_PUSH_VLAN = 1 << 19,
OFPUTIL_A_POP_VLAN = 1 << 20,
OFPUTIL_A_PUSH_MPLS = 1 << 21,
OFPUTIL_A_POP_MPLS = 1 << 22,
OFPUTIL_A_SET_QUEUE = 1 << 23,
OFPUTIL_A_GROUP = 1 << 24,
OFPUTIL_A_SET_NW_TTL = 1 << 25,
OFPUTIL_A_DEC_NW_TTL = 1 << 26,
OFPUTIL_A_SET_FIELD = 1 << 27,
};
/* Abstract ofp_switch_features. */ /* Abstract ofp_switch_features. */
struct ofputil_switch_features { struct ofputil_switch_features {
uint64_t datapath_id; /* Datapath unique ID. */ uint64_t datapath_id; /* Datapath unique ID. */
@@ -566,7 +535,7 @@ struct ofputil_switch_features {
uint8_t n_tables; /* Number of tables supported by datapath. */ uint8_t n_tables; /* Number of tables supported by datapath. */
uint8_t auxiliary_id; /* Identify auxiliary connections */ uint8_t auxiliary_id; /* Identify auxiliary connections */
enum ofputil_capabilities capabilities; enum ofputil_capabilities capabilities;
enum ofputil_action_bitmap actions; uint64_t ofpacts; /* Bitmap of OFPACT_* bits. */
}; };
enum ofperr ofputil_decode_switch_features(const struct ofp_header *, enum ofperr ofputil_decode_switch_features(const struct ofp_header *,
@@ -650,7 +619,7 @@ struct ofputil_table_features {
* - 'apply' reports features available in an "apply_actions" * - 'apply' reports features available in an "apply_actions"
* instruction. */ * instruction. */
struct ofputil_table_action_features { struct ofputil_table_action_features {
uint32_t actions; /* Bitmap of supported OFPAT*. */ uint64_t ofpacts; /* Bitmap of supported OFPACT_*. */
struct mf_bitmap set_fields; /* Fields for "set-field". */ struct mf_bitmap set_fields; /* Fields for "set-field". */
} write, apply; } write, apply;
} nonmiss, miss; } nonmiss, miss;
@@ -798,13 +767,30 @@ struct ofpbuf *ofputil_encode_role_status(
enum ofperr ofputil_decode_role_status(const struct ofp_header *oh, enum ofperr ofputil_decode_role_status(const struct ofp_header *oh,
struct ofputil_role_status *rs); struct ofputil_role_status *rs);
/* Abstract table stats. /* Abstract table stats. */
* struct ofputil_table_stats {
* For now we use ofp12_table_stats as a superset of the other protocol uint8_t table_id;
* versions' table stats. */ char name[OFP_MAX_TABLE_NAME_LEN];
ovs_be64 metadata_match; /* Bits of metadata table can match. */
ovs_be64 metadata_write; /* Bits of metadata table can write. */
uint32_t config; /* Bitmap of OFPTC_* values */
uint32_t max_entries; /* Max number of entries supported. */
struct mf_bitmap match; /* Fields table can match. */
struct mf_bitmap wildcards; /* Fields table can wildcard. */
uint64_t write_ofpacts; /* OFPACT_* supported on Write-Actions. */
uint64_t apply_ofpacts; /* OFPACT_* supported on Apply-Actions. */
struct mf_bitmap write_setfields; /* Fields that can be set in W-A. */
struct mf_bitmap apply_setfields; /* Fields that can be set in A-A. */
uint32_t instructions; /* Bitmap of OFPIT_* values supported. */
uint32_t active_count; /* Number of active entries. */
uint64_t lookup_count; /* Number of packets looked up in table. */
uint64_t matched_count; /* Number of packets that hit table. */
};
struct ofpbuf *ofputil_encode_table_stats_reply( struct ofpbuf *ofputil_encode_table_stats_reply(
const struct ofp12_table_stats[], int n, const struct ofputil_table_stats[], int n,
const struct ofp_header *request); const struct ofp_header *request);
/* Queue configuration request. */ /* Queue configuration request. */
@@ -1099,9 +1085,7 @@ struct ofputil_group_features {
uint32_t types; /* Bitmap of OFPGT_* values supported. */ uint32_t types; /* Bitmap of OFPGT_* values supported. */
uint32_t capabilities; /* Bitmap of OFPGFC12_* capability supported. */ uint32_t capabilities; /* Bitmap of OFPGFC12_* capability supported. */
uint32_t max_groups[4]; /* Maximum number of groups for each type. */ uint32_t max_groups[4]; /* Maximum number of groups for each type. */
uint64_t ofpacts[4]; /* Bitmaps of supported OFPACT_* */
/* Bitmaps of OFPAT_* that are supported. OF1.2+ actions only. */
uint32_t actions[4];
}; };
/* Group desc reply, independent of protocol. */ /* Group desc reply, independent of protocol. */

View File

@@ -1500,37 +1500,26 @@ flush(struct ofproto *ofproto_)
static void static void
get_features(struct ofproto *ofproto_ OVS_UNUSED, get_features(struct ofproto *ofproto_ OVS_UNUSED,
bool *arp_match_ip, enum ofputil_action_bitmap *actions) bool *arp_match_ip, uint64_t *ofpacts)
{ {
*arp_match_ip = true; *arp_match_ip = true;
*actions = (OFPUTIL_A_OUTPUT | *ofpacts = (UINT64_C(1) << N_OFPACTS) - 1;
OFPUTIL_A_SET_VLAN_VID |
OFPUTIL_A_SET_VLAN_PCP |
OFPUTIL_A_STRIP_VLAN |
OFPUTIL_A_SET_DL_SRC |
OFPUTIL_A_SET_DL_DST |
OFPUTIL_A_SET_NW_SRC |
OFPUTIL_A_SET_NW_DST |
OFPUTIL_A_SET_NW_TOS |
OFPUTIL_A_SET_TP_SRC |
OFPUTIL_A_SET_TP_DST |
OFPUTIL_A_ENQUEUE);
} }
static void static void
get_tables(struct ofproto *ofproto, struct ofp12_table_stats *ots) get_tables(struct ofproto *ofproto, struct ofputil_table_stats *stats)
{ {
int i; int i;
strcpy(ots->name, "classifier"); strcpy(stats->name, "classifier");
for (i = 0; i < ofproto->n_tables; i++) { for (i = 0; i < ofproto->n_tables; i++) {
unsigned long missed, matched; unsigned long missed, matched;
atomic_read(&ofproto->tables[i].n_matched, &matched); atomic_read(&ofproto->tables[i].n_matched, &matched);
ots[i].matched_count = htonll(matched); stats[i].matched_count = matched;
atomic_read(&ofproto->tables[i].n_missed, &missed); atomic_read(&ofproto->tables[i].n_missed, &missed);
ots[i].lookup_count = htonll(matched + missed); stats[i].lookup_count = matched + missed;
} }
} }

View File

@@ -774,30 +774,30 @@ struct ofproto_class {
* supports matching IP addresses inside ARP requests and replies, false * supports matching IP addresses inside ARP requests and replies, false
* otherwise. * otherwise.
* *
* The implementation should store in '*actions' a bitmap of the supported * The implementation should store in '*ofpacts' a bitmap of the supported
* OpenFlow actions. Vendor actions are not included in '*actions'. */ * OFPACT_* actions. */
void (*get_features)(struct ofproto *ofproto, void (*get_features)(struct ofproto *ofproto,
bool *arp_match_ip, bool *arp_match_ip,
enum ofputil_action_bitmap *actions); uint64_t *ofpacts);
/* Helper for the OpenFlow OFPST_TABLE statistics request. /* Helper for the OpenFlow OFPST_TABLE statistics request.
* *
* The 'ots' array contains 'ofproto->n_tables' elements. Each element is * The 'stats' array contains 'ofproto->n_tables' elements. Each element is
* initialized as: * initialized as:
* *
* - 'table_id' to the array index. * - 'table_id' to the array index.
* *
* - 'name' to "table#" where # is the table ID. * - 'name' to "table#" where # is the table ID.
* *
* - 'match' and 'wildcards' to OFPXMT12_MASK. * - 'match' and 'wildcards' to all fields.
* *
* - 'write_actions' and 'apply_actions' to OFPAT12_OUTPUT. * - 'write_actions' and 'apply_actions' to all actions.
* *
* - 'write_setfields' and 'apply_setfields' to OFPXMT12_MASK. * - 'write_setfields' and 'apply_setfields' to all writable fields.
* *
* - 'metadata_match' and 'metadata_write' to OVS_BE64_MAX. * - 'metadata_match' and 'metadata_write' to OVS_BE64_MAX.
* *
* - 'instructions' to OFPIT11_ALL. * - 'instructions' to all instructions.
* *
* - 'config' to OFPTC11_TABLE_MISS_MASK. * - 'config' to OFPTC11_TABLE_MISS_MASK.
* *
@@ -838,11 +838,9 @@ struct ofproto_class {
* *
* - 'matched_count' to the number of packets looked up in this flow * - 'matched_count' to the number of packets looked up in this flow
* table so far that matched one of the flow entries. * table so far that matched one of the flow entries.
*
* All of the members of struct ofp12_table_stats are in network byte
* order.
*/ */
void (*get_tables)(struct ofproto *ofproto, struct ofp12_table_stats *ots); void (*get_tables)(struct ofproto *ofproto,
struct ofputil_table_stats *stats);
/* ## ---------------- ## */ /* ## ---------------- ## */
/* ## ofport Functions ## */ /* ## ofport Functions ## */

View File

@@ -524,28 +524,10 @@ ofproto_create(const char *datapath_name, const char *datapath_type,
ovs_mutex_unlock(&ofproto_mutex); ovs_mutex_unlock(&ofproto_mutex);
ofproto->ogf.capabilities = OFPGFC_CHAINING | OFPGFC_SELECT_LIVENESS | ofproto->ogf.capabilities = OFPGFC_CHAINING | OFPGFC_SELECT_LIVENESS |
OFPGFC_SELECT_WEIGHT; OFPGFC_SELECT_WEIGHT;
ofproto->ogf.max_groups[OFPGT11_ALL] = OFPG_MAX; for (i = 0; i < 4; i++) {
ofproto->ogf.max_groups[OFPGT11_SELECT] = OFPG_MAX; ofproto->ogf.max_groups[i] = OFPG_MAX;
ofproto->ogf.max_groups[OFPGT11_INDIRECT] = OFPG_MAX; ofproto->ogf.ofpacts[i] = (UINT64_C(1) << N_OFPACTS) - 1;
ofproto->ogf.max_groups[OFPGT11_FF] = OFPG_MAX; }
ofproto->ogf.actions[0] =
(1 << OFPAT11_OUTPUT) |
(1 << OFPAT11_COPY_TTL_OUT) |
(1 << OFPAT11_COPY_TTL_IN) |
(1 << OFPAT11_SET_MPLS_TTL) |
(1 << OFPAT11_DEC_MPLS_TTL) |
(1 << OFPAT11_PUSH_VLAN) |
(1 << OFPAT11_POP_VLAN) |
(1 << OFPAT11_PUSH_MPLS) |
(1 << OFPAT11_POP_MPLS) |
(1 << OFPAT11_SET_QUEUE) |
(1 << OFPAT11_GROUP) |
(1 << OFPAT11_SET_NW_TTL) |
(1 << OFPAT11_DEC_NW_TTL) |
(1 << OFPAT12_SET_FIELD);
/* not supported:
* (1 << OFPAT13_PUSH_PBB) |
* (1 << OFPAT13_POP_PBB) */
error = ofproto->ofproto_class->construct(ofproto); error = ofproto->ofproto_class->construct(ofproto);
if (error) { if (error) {
@@ -2805,8 +2787,8 @@ handle_features_request(struct ofconn *ofconn, const struct ofp_header *oh)
struct ofpbuf *b; struct ofpbuf *b;
ofproto->ofproto_class->get_features(ofproto, &arp_match_ip, ofproto->ofproto_class->get_features(ofproto, &arp_match_ip,
&features.actions); &features.ofpacts);
ovs_assert(features.actions & OFPUTIL_A_OUTPUT); /* sanity check */ ovs_assert(features.ofpacts & (UINT64_C(1) << OFPACT_OUTPUT));
features.datapath_id = ofproto->datapath_id; features.datapath_id = ofproto->datapath_id;
features.n_buffers = pktbuf_capacity(); features.n_buffers = pktbuf_capacity();
@@ -3081,37 +3063,44 @@ static enum ofperr
handle_table_stats_request(struct ofconn *ofconn, handle_table_stats_request(struct ofconn *ofconn,
const struct ofp_header *request) const struct ofp_header *request)
{ {
struct mf_bitmap rw_fields = MF_BITMAP_INITIALIZER;
struct ofproto *p = ofconn_get_ofproto(ofconn); struct ofproto *p = ofconn_get_ofproto(ofconn);
struct ofp12_table_stats *ots; struct ofputil_table_stats *stats;
struct ofpbuf *msg; struct ofpbuf *msg;
int n_tables; int n_tables;
size_t i; size_t i;
for (i = 0; i < MFF_N_IDS; i++) {
if (mf_from_id(i)->writable) {
bitmap_set1(rw_fields.bm, i);
}
}
/* Set up default values. /* Set up default values.
* *
* ofp12_table_stats is used as a generic structure as * ofp12_table_stats is used as a generic structure as
* it is able to hold all the fields for ofp10_table_stats * it is able to hold all the fields for ofp10_table_stats
* and ofp11_table_stats (and of course itself). * and ofp11_table_stats (and of course itself).
*/ */
ots = xcalloc(p->n_tables, sizeof *ots); stats = xcalloc(p->n_tables, sizeof *stats);
for (i = 0; i < p->n_tables; i++) { for (i = 0; i < p->n_tables; i++) {
ots[i].table_id = i; stats[i].table_id = i;
sprintf(ots[i].name, "table%"PRIuSIZE, i); sprintf(stats[i].name, "table%"PRIuSIZE, i);
ots[i].match = htonll(OFPXMT13_MASK); bitmap_set_multiple(stats[i].match.bm, 0, MFF_N_IDS, 1);
ots[i].wildcards = htonll(OFPXMT13_MASK); bitmap_set_multiple(stats[i].wildcards.bm, 0, MFF_N_IDS, 1);
ots[i].write_actions = htonl(OFPAT11_OUTPUT); stats[i].write_ofpacts = (UINT64_C(1) << N_OFPACTS) - 1;
ots[i].apply_actions = htonl(OFPAT11_OUTPUT); stats[i].apply_ofpacts = (UINT64_C(1) << N_OFPACTS) - 1;
ots[i].write_setfields = htonll(OFPXMT13_MASK); stats[i].write_setfields = rw_fields;
ots[i].apply_setfields = htonll(OFPXMT13_MASK); stats[i].apply_setfields = rw_fields;
ots[i].metadata_match = OVS_BE64_MAX; stats[i].metadata_match = OVS_BE64_MAX;
ots[i].metadata_write = OVS_BE64_MAX; stats[i].metadata_write = OVS_BE64_MAX;
ots[i].instructions = htonl(OFPIT11_ALL); stats[i].instructions = OFPIT13_ALL;
ots[i].config = htonl(OFPTC11_TABLE_MISS_MASK); stats[i].config = OFPTC11_TABLE_MISS_MASK;
ots[i].max_entries = htonl(1000000); /* An arbitrary big number. */ stats[i].max_entries = 1000000; /* An arbitrary big number. */
ots[i].active_count = htonl(classifier_count(&p->tables[i].cls)); stats[i].active_count = classifier_count(&p->tables[i].cls);
} }
p->ofproto_class->get_tables(p, ots); p->ofproto_class->get_tables(p, stats);
/* Post-process the tables, dropping hidden tables. */ /* Post-process the tables, dropping hidden tables. */
n_tables = p->n_tables; n_tables = p->n_tables;
@@ -3124,18 +3113,18 @@ handle_table_stats_request(struct ofconn *ofconn,
} }
if (table->name) { if (table->name) {
ovs_strzcpy(ots[i].name, table->name, sizeof ots[i].name); ovs_strzcpy(stats[i].name, table->name, sizeof stats[i].name);
} }
if (table->max_flows < ntohl(ots[i].max_entries)) { if (table->max_flows < stats[i].max_entries) {
ots[i].max_entries = htonl(table->max_flows); stats[i].max_entries = table->max_flows;
} }
} }
msg = ofputil_encode_table_stats_reply(ots, n_tables, request); msg = ofputil_encode_table_stats_reply(stats, n_tables, request);
ofconn_send_reply(ofconn, msg); ofconn_send_reply(ofconn, msg);
free(ots); free(stats);
return 0; return 0;
} }

View File

@@ -203,7 +203,7 @@ ff fe 50 54 00 00 00 01 62 72 30 00 00 00 00 00 \
OFPT_FEATURES_REPLY (xid=0x1): dpid:0000505400000001 OFPT_FEATURES_REPLY (xid=0x1): dpid:0000505400000001
n_tables:2, n_buffers:256 n_tables:2, n_buffers:256
capabilities: FLOW_STATS TABLE_STATS PORT_STATS ARP_MATCH_IP capabilities: FLOW_STATS TABLE_STATS PORT_STATS ARP_MATCH_IP
actions: OUTPUT SET_VLAN_VID SET_VLAN_PCP STRIP_VLAN SET_DL_SRC SET_DL_DST SET_NW_SRC SET_NW_DST SET_NW_TOS SET_TP_SRC SET_TP_DST ENQUEUE actions: output enqueue set_vlan_vid set_vlan_pcp strip_vlan mod_dl_src mod_dl_dst mod_nw_src mod_nw_dst mod_nw_tos mod_tp_src mod_tp_dst
1(eth1): addr:50:54:00:00:00:02 1(eth1): addr:50:54:00:00:00:02
config: 0 config: 0
state: 0 state: 0
@@ -1923,20 +1923,24 @@ AT_CHECK([ovs-ofctl ofp-print "\
03 13 00 38 00 00 00 02 00 08 00 00 00 00 00 00 \ 03 13 00 38 00 00 00 02 00 08 00 00 00 00 00 00 \
00 00 00 0f 00 00 00 0f \ 00 00 00 0f 00 00 00 0f \
00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 \ 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 \
00 00 00 01 00 00 00 03 00 00 00 07 00 00 00 0f \ 00 00 00 01 00 02 00 01 00 06 00 01 00 0e 00 01 \
"], [0], [dnl "], [0], [dnl
OFPST_GROUP_FEATURES reply (OF1.2) (xid=0x2): OFPST_GROUP_FEATURES reply (OF1.2) (xid=0x2):
Group table: Group table:
Types: 0xf Types: 0xf
Capabilities: 0xf Capabilities: 0xf
All group : all group:
max_groups = 0x1 actions=0x00000001 max_groups=0x1
Select group : actions: output
max_groups = 0x2 actions=0x00000003 select group:
Indirect group : max_groups=0x2
max_groups = 0x3 actions=0x00000007 actions: output push_vlan
Fast Failover group : indirect group:
max_groups = 0x4 actions=0x0000000f max_groups=0x3
actions: output strip_vlan push_vlan
fast failover group:
max_groups=0x4
actions: output strip_vlan push_vlan push_mpls
]) ])
AT_CLEANUP AT_CLEANUP
@@ -2275,7 +2279,7 @@ f5 f6 f7 f8 f9 fa fb fc fd 00 00 00 00 00 00 00 \
next tables: 1-253 next tables: 1-253
instructions: apply_actions,clear_actions,write_actions,write_metadata,goto_table instructions: apply_actions,clear_actions,write_actions,write_metadata,goto_table
Write-Actions and Apply-Actions features: Write-Actions and Apply-Actions features:
actions: output,copy_ttl_out,copy_ttl_in,set_mpls_ttl,dec_mpls_ttl,push_vlan,pop_vlan,push_mpls,pop_mpls,set_queue,group,set_nw_ttl,dec_nw_ttl,set_field,push_pbb,pop_pbb actions: output group set_field strip_vlan push_vlan mod_nw_ttl dec_ttl set_mpls_ttl dec_mpls_ttl push_mpls pop_mpls set_queue
supported on Set-Field: tun_id,tun_src,tun_dst,metadata,in_port,in_port_oxm,pkt_mark,reg0,reg1,reg2,reg3,reg4,reg5,reg6,reg7,eth_src,eth_dst,vlan_tci,vlan_vid,vlan_pcp,mpls_label,mpls_tc,ip_src,ip_dst,ipv6_src,ipv6_dst,nw_tos,ip_dscp,nw_ecn,nw_ttl,arp_op,arp_spa,arp_tpa,arp_sha,arp_tha,tcp_src,tcp_dst,udp_src,udp_dst,sctp_src,sctp_dst supported on Set-Field: tun_id,tun_src,tun_dst,metadata,in_port,in_port_oxm,pkt_mark,reg0,reg1,reg2,reg3,reg4,reg5,reg6,reg7,eth_src,eth_dst,vlan_tci,vlan_vid,vlan_pcp,mpls_label,mpls_tc,ip_src,ip_dst,ipv6_src,ipv6_dst,nw_tos,ip_dscp,nw_ecn,nw_ttl,arp_op,arp_spa,arp_tpa,arp_sha,arp_tha,tcp_src,tcp_dst,udp_src,udp_dst,sctp_src,sctp_dst
matching: matching:
tun_id: exact match or wildcard tun_id: exact match or wildcard

View File

@@ -36,7 +36,7 @@ AT_CHECK([STRIP_XIDS stdout], [0], [dnl
OFPT_FEATURES_REPLY: dpid:fedcba9876543210 OFPT_FEATURES_REPLY: dpid:fedcba9876543210
n_tables:254, n_buffers:256 n_tables:254, n_buffers:256
capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP
actions: OUTPUT SET_VLAN_VID SET_VLAN_PCP STRIP_VLAN SET_DL_SRC SET_DL_DST SET_NW_SRC SET_NW_DST SET_NW_TOS SET_TP_SRC SET_TP_DST ENQUEUE actions: output enqueue set_vlan_vid set_vlan_pcp strip_vlan mod_dl_src mod_dl_dst mod_nw_src mod_nw_dst mod_nw_tos mod_tp_src mod_tp_dst
LOCAL(br0): addr:aa:55:aa:55:00:00 LOCAL(br0): addr:aa:55:aa:55:00:00
config: PORT_DOWN config: PORT_DOWN
state: LINK_DOWN state: LINK_DOWN
@@ -58,7 +58,7 @@ s/00:0.$/00:0x/' < stdout]],
OFPT_FEATURES_REPLY: dpid:fedcba9876543210 OFPT_FEATURES_REPLY: dpid:fedcba9876543210
n_tables:254, n_buffers:256 n_tables:254, n_buffers:256
capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP
actions: OUTPUT SET_VLAN_VID SET_VLAN_PCP STRIP_VLAN SET_DL_SRC SET_DL_DST SET_NW_SRC SET_NW_DST SET_NW_TOS SET_TP_SRC SET_TP_DST ENQUEUE actions: output enqueue set_vlan_vid set_vlan_pcp strip_vlan mod_dl_src mod_dl_dst mod_nw_src mod_nw_dst mod_nw_tos mod_tp_src mod_tp_dst
1(p1): addr:aa:55:aa:55:00:0x 1(p1): addr:aa:55:aa:55:00:0x
config: PORT_DOWN config: PORT_DOWN
state: LINK_DOWN state: LINK_DOWN
@@ -451,7 +451,7 @@ do
OFPT_FEATURES_REPLY: dpid:fedcba9876543210 OFPT_FEATURES_REPLY: dpid:fedcba9876543210
n_tables:254, n_buffers:256 n_tables:254, n_buffers:256
capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP
actions: OUTPUT SET_VLAN_VID SET_VLAN_PCP STRIP_VLAN SET_DL_SRC SET_DL_DST SET_NW_SRC SET_NW_DST SET_NW_TOS SET_TP_SRC SET_TP_DST ENQUEUE actions: output enqueue set_vlan_vid set_vlan_pcp strip_vlan mod_dl_src mod_dl_dst mod_nw_src mod_nw_dst mod_nw_tos mod_tp_src mod_tp_dst
LOCAL(br0): addr:aa:55:aa:55:00:00 LOCAL(br0): addr:aa:55:aa:55:00:00
config: $config config: $config
state: $state state: $state
@@ -1064,13 +1064,13 @@ AT_CLEANUP
AT_SETUP([ofproto - flow table configuration (OpenFlow 1.2)]) AT_SETUP([ofproto - flow table configuration (OpenFlow 1.2)])
OVS_VSWITCHD_START OVS_VSWITCHD_START
# Check the default configuration. # Check the default configuration.
(mid="wild=0xfffffffff, max=1000000," (mid="wild=0x1ffffffffd, max=1000000,"
tail=" tail="
lookup=0, matched=0 lookup=0, matched=0
match=0xfffffffff, instructions=0x00000007, config=0x00000003 match=0x1ffffffffd, instructions=0x00000007, config=0x00000003
write_actions=0x00000000, apply_actions=0x00000000 write_actions=0x03ff8001, apply_actions=0x03ff8001
write_setfields=0x0000000fffffffff write_setfields=0x0000000c0fe7fbdd
apply_setfields=0x0000000fffffffff apply_setfields=0x0000000c0fe7fbdd
metadata_match=0xffffffffffffffff metadata_match=0xffffffffffffffff
metadata_write=0xffffffffffffffff" metadata_write=0xffffffffffffffff"
echo "OFPST_TABLE reply (OF1.2) (xid=0x2): 254 tables echo "OFPST_TABLE reply (OF1.2) (xid=0x2): 254 tables
@@ -1095,9 +1095,9 @@ AT_CHECK(
# Check that the configuration was updated. # Check that the configuration was updated.
mv expout orig-expout mv expout orig-expout
(echo "OFPST_TABLE reply (OF1.2) (xid=0x2): 254 tables (echo "OFPST_TABLE reply (OF1.2) (xid=0x2): 254 tables
0: main : wild=0xfffffffff, max=1000000, active=0" 0: main : wild=0x1ffffffffd, max=1000000, active=0"
tail -n +3 orig-expout | head -7 tail -n +3 orig-expout | head -7
echo " 1: table1 : wild=0xfffffffff, max= 1024, active=0" echo " 1: table1 : wild=0x1ffffffffd, max= 1024, active=0"
tail -n +11 orig-expout) > expout tail -n +11 orig-expout) > expout
AT_CHECK([ovs-ofctl -O OpenFlow12 dump-tables br0], [0], [expout]) AT_CHECK([ovs-ofctl -O OpenFlow12 dump-tables br0], [0], [expout])
OVS_VSWITCHD_STOP OVS_VSWITCHD_STOP