X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fofp-util.h;h=13195c76c2b0b2a37a5aa5105fe32dfbb0a5d896;hb=5aa0fe5bef0462e3c3c6f31e9f2ed51269ffd467;hp=4666a88f37bdcde3d9382ba6bafdb06c1773bee9;hpb=2e4f5fcf3f5837de6805ccad58cd852a7cca595d;p=sliver-openvswitch.git diff --git a/lib/ofp-util.h b/lib/ofp-util.h index 4666a88f3..13195c76c 100644 --- a/lib/ofp-util.h +++ b/lib/ofp-util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010 Nicira Networks. + * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,12 +29,9 @@ struct cls_rule; struct ofpbuf; -/* Alignment of ofp_actions. */ -#define OFP_ACTION_ALIGN 8 - /* Basic decoding and length validation of OpenFlow messages. */ enum ofputil_msg_code { - OFPUTIL_INVALID, + OFPUTIL_MSG_INVALID, /* OFPT_* messages. */ OFPUTIL_OFPT_HELLO, @@ -74,14 +71,14 @@ enum ofputil_msg_code { OFPUTIL_OFPST_AGGREGATE_REPLY, /* NXT_* messages. */ - OFPUTIL_NXT_STATUS_REQUEST, - OFPUTIL_NXT_STATUS_REPLY, - OFPUTIL_NXT_TUN_ID_FROM_COOKIE, OFPUTIL_NXT_ROLE_REQUEST, OFPUTIL_NXT_ROLE_REPLY, OFPUTIL_NXT_SET_FLOW_FORMAT, + OFPUTIL_NXT_FLOW_MOD_TABLE_ID, OFPUTIL_NXT_FLOW_MOD, OFPUTIL_NXT_FLOW_REMOVED, + OFPUTIL_NXT_SET_PACKET_IN_FORMAT, + OFPUTIL_NXT_PACKET_IN, /* NXST_* stat requests. */ OFPUTIL_NXST_FLOW_REQUEST, @@ -95,27 +92,55 @@ enum ofputil_msg_code { struct ofputil_msg_type; int ofputil_decode_msg_type(const struct ofp_header *, const struct ofputil_msg_type **); +int ofputil_decode_msg_type_partial(const struct ofp_header *, size_t length, + const struct ofputil_msg_type **); enum ofputil_msg_code ofputil_msg_type_code(const struct ofputil_msg_type *); const char *ofputil_msg_type_name(const struct ofputil_msg_type *); +/* Port numbers. */ +int ofputil_check_output_port(uint16_t ofp_port, int max_ports); +bool ofputil_port_from_string(const char *, uint16_t *port); +void ofputil_format_port(uint16_t port, struct ds *); + /* Converting OFPFW_NW_SRC_MASK and OFPFW_NW_DST_MASK wildcard bit counts to * and from IP bitmasks. */ ovs_be32 ofputil_wcbits_to_netmask(int wcbits); int ofputil_netmask_to_wcbits(ovs_be32 netmask); /* Work with OpenFlow 1.0 ofp_match. */ +void ofputil_wildcard_from_openflow(uint32_t ofpfw, struct flow_wildcards *); void ofputil_cls_rule_from_match(const struct ofp_match *, - unsigned int priority, enum nx_flow_format, - uint64_t cookie, struct cls_rule *); -void ofputil_cls_rule_to_match(const struct cls_rule *, enum nx_flow_format, - struct ofp_match *); -void normalize_match(struct ofp_match *); -char *ofp_match_to_literal_string(const struct ofp_match *match); + unsigned int priority, struct cls_rule *); +void ofputil_normalize_rule(struct cls_rule *, enum nx_flow_format); +void ofputil_cls_rule_to_match(const struct cls_rule *, struct ofp_match *); + +/* dl_type translation between OpenFlow and 'struct flow' format. */ +ovs_be16 ofputil_dl_type_to_openflow(ovs_be16 flow_dl_type); +ovs_be16 ofputil_dl_type_from_openflow(ovs_be16 ofp_dl_type); + +/* Flow formats. */ +bool ofputil_flow_format_is_valid(enum nx_flow_format); +const char *ofputil_flow_format_to_string(enum nx_flow_format); +int ofputil_flow_format_from_string(const char *); +enum nx_flow_format ofputil_min_flow_format(const struct cls_rule *); + +struct ofpbuf *ofputil_make_set_flow_format(enum nx_flow_format); + +/* PACKET_IN. */ +bool ofputil_packet_in_format_is_valid(enum nx_packet_in_format); +int ofputil_packet_in_format_from_string(const char *); +const char *ofputil_packet_in_format_to_string(enum nx_packet_in_format); +struct ofpbuf *ofputil_make_set_packet_in_format(enum nx_packet_in_format); + +/* NXT_FLOW_MOD_TABLE_ID extension. */ +struct ofpbuf *ofputil_make_flow_mod_table_id(bool flow_mod_table_id); /* Flow format independent flow_mod. */ -struct flow_mod { +struct ofputil_flow_mod { struct cls_rule cr; ovs_be64 cookie; + ovs_be64 cookie_mask; + uint8_t table_id; uint16_t command; uint16_t idle_timeout; uint16_t hard_timeout; @@ -126,24 +151,97 @@ struct flow_mod { size_t n_actions; }; -int ofputil_decode_flow_mod(struct flow_mod *, const struct ofp_header *, - enum nx_flow_format); -struct ofpbuf *ofputil_encode_flow_mod(const struct flow_mod *, - enum nx_flow_format); +int ofputil_decode_flow_mod(struct ofputil_flow_mod *, + const struct ofp_header *, bool flow_mod_table_id); +struct ofpbuf *ofputil_encode_flow_mod(const struct ofputil_flow_mod *, + enum nx_flow_format, + bool flow_mod_table_id); /* Flow stats or aggregate stats request, independent of flow format. */ -struct flow_stats_request { +struct ofputil_flow_stats_request { bool aggregate; /* Aggregate results? */ struct cls_rule match; + ovs_be64 cookie; + ovs_be64 cookie_mask; uint16_t out_port; uint8_t table_id; }; -int ofputil_decode_flow_stats_request(struct flow_stats_request *, - const struct ofp_header *, - enum nx_flow_format); +int ofputil_decode_flow_stats_request(struct ofputil_flow_stats_request *, + const struct ofp_header *); struct ofpbuf *ofputil_encode_flow_stats_request( - const struct flow_stats_request *, enum nx_flow_format); + const struct ofputil_flow_stats_request *, enum nx_flow_format); + +/* Flow stats reply, independent of flow format. */ +struct ofputil_flow_stats { + struct cls_rule rule; + ovs_be64 cookie; + uint8_t table_id; + uint32_t duration_sec; + uint32_t duration_nsec; + uint16_t idle_timeout; + uint16_t hard_timeout; + uint64_t packet_count; /* Packet count, UINT64_MAX if unknown. */ + uint64_t byte_count; /* Byte count, UINT64_MAX if unknown. */ + union ofp_action *actions; + size_t n_actions; +}; + +int ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *, + struct ofpbuf *msg); +void ofputil_append_flow_stats_reply(const struct ofputil_flow_stats *, + struct list *replies); + +/* Aggregate stats reply, independent of flow format. */ +struct ofputil_aggregate_stats { + uint64_t packet_count; /* Packet count, UINT64_MAX if unknown. */ + uint64_t byte_count; /* Byte count, UINT64_MAX if unknown. */ + uint32_t flow_count; +}; + +struct ofpbuf *ofputil_encode_aggregate_stats_reply( + const struct ofputil_aggregate_stats *stats, + const struct ofp_stats_msg *request); + +/* Flow removed message, independent of flow format. */ +struct ofputil_flow_removed { + struct cls_rule rule; + ovs_be64 cookie; + uint8_t reason; /* One of OFPRR_*. */ + uint32_t duration_sec; + uint32_t duration_nsec; + uint16_t idle_timeout; + uint64_t packet_count; /* Packet count, UINT64_MAX if unknown. */ + uint64_t byte_count; /* Byte count, UINT64_MAX if unknown. */ +}; + +int ofputil_decode_flow_removed(struct ofputil_flow_removed *, + const struct ofp_header *); +struct ofpbuf *ofputil_encode_flow_removed(const struct ofputil_flow_removed *, + enum nx_flow_format); + +/* Abstract packet-in message. */ +struct ofputil_packet_in { + const void *packet; + size_t packet_len; + + uint8_t reason; /* One of OFPR_*. */ + uint8_t table_id; + ovs_be64 cookie; + + uint32_t buffer_id; + int send_len; + uint16_t total_len; /* Full length of frame. */ + + struct flow_metadata fmd; /* Metadata at creation time. */ +}; + +int ofputil_decode_packet_in(struct ofputil_packet_in *, + const struct ofp_header *); +struct ofpbuf *ofputil_encode_packet_in(const struct ofputil_packet_in *, + enum nx_packet_in_format); +int ofputil_decode_packet_in(struct ofputil_packet_in *pi, + const struct ofp_header *oh); /* OpenFlow protocol utility functions. */ void *make_openflow(size_t openflow_len, uint8_t type, struct ofpbuf **); @@ -164,13 +262,22 @@ void *put_nxmsg_xid(size_t openflow_len, uint32_t subtype, ovs_be32 xid, void update_openflow_length(struct ofpbuf *); -void *ofputil_make_stats_request(size_t body_len, uint16_t type, - struct ofpbuf **); -void *ofputil_make_nxstats_request(size_t openflow_len, uint32_t subtype, - struct ofpbuf **); +void *ofputil_make_stats_request(size_t openflow_len, uint16_t type, + uint32_t subtype, struct ofpbuf **); +void *ofputil_make_stats_reply(size_t openflow_len, + const struct ofp_stats_msg *request, + struct ofpbuf **); + +void ofputil_start_stats_reply(const struct ofp_stats_msg *request, + struct list *); +struct ofpbuf *ofputil_reserve_stats_reply(size_t len, struct list *); +void *ofputil_append_stats_reply(size_t len, struct list *); const void *ofputil_stats_body(const struct ofp_header *); -size_t ofputil_stats_body_len(const struct ofp_header *oh); +size_t ofputil_stats_body_len(const struct ofp_header *); + +const void *ofputil_nxstats_body(const struct ofp_header *); +size_t ofputil_nxstats_body_len(const struct ofp_header *); struct ofpbuf *make_flow_mod(uint16_t command, const struct cls_rule *, size_t actions_len); @@ -194,26 +301,133 @@ struct ofpbuf *make_unbuffered_packet_out(const struct ofpbuf *packet, struct ofpbuf *make_echo_request(void); struct ofpbuf *make_echo_reply(const struct ofp_header *rq); -struct flow_stats_iterator { - const uint8_t *pos, *end; +const char *ofputil_frag_handling_to_string(enum ofp_config_flags); +bool ofputil_frag_handling_from_string(const char *, enum ofp_config_flags *); + +/* Actions. */ + +/* The type of an action. + * + * For each implemented OFPAT_* and NXAST_* action type, there is a + * corresponding constant prefixed with OFPUTIL_, e.g.: + * + * OFPUTIL_OFPAT_OUTPUT + * OFPUTIL_OFPAT_SET_VLAN_VID + * OFPUTIL_OFPAT_SET_VLAN_PCP + * OFPUTIL_OFPAT_STRIP_VLAN + * OFPUTIL_OFPAT_SET_DL_SRC + * OFPUTIL_OFPAT_SET_DL_DST + * OFPUTIL_OFPAT_SET_NW_SRC + * OFPUTIL_OFPAT_SET_NW_DST + * OFPUTIL_OFPAT_SET_NW_TOS + * OFPUTIL_OFPAT_SET_TP_SRC + * OFPUTIL_OFPAT_SET_TP_DST + * OFPUTIL_OFPAT_ENQUEUE + * OFPUTIL_NXAST_RESUBMIT + * OFPUTIL_NXAST_SET_TUNNEL + * OFPUTIL_NXAST_SET_QUEUE + * OFPUTIL_NXAST_POP_QUEUE + * OFPUTIL_NXAST_REG_MOVE + * OFPUTIL_NXAST_REG_LOAD + * OFPUTIL_NXAST_NOTE + * OFPUTIL_NXAST_SET_TUNNEL64 + * OFPUTIL_NXAST_MULTIPATH + * OFPUTIL_NXAST_AUTOPATH + * OFPUTIL_NXAST_BUNDLE + * OFPUTIL_NXAST_BUNDLE_LOAD + * OFPUTIL_NXAST_RESUBMIT_TABLE + * OFPUTIL_NXAST_OUTPUT_REG + * + * (The above list helps developers who want to "grep" for these definitions.) + */ +enum ofputil_action_code { +#define OFPAT_ACTION(ENUM, STRUCT, NAME) OFPUTIL_##ENUM, +#define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) OFPUTIL_##ENUM, +#include "ofp-util.def" }; -const struct ofp_flow_stats *flow_stats_first(struct flow_stats_iterator *, - const struct ofp_stats_reply *); -const struct ofp_flow_stats *flow_stats_next(struct flow_stats_iterator *); -struct actions_iterator { - const union ofp_action *pos, *end; +/* The number of values of "enum ofputil_action_code". */ +enum { +#define OFPAT_ACTION(ENUM, STRUCT, NAME) + 1 +#define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) + 1 + OFPUTIL_N_ACTIONS = 0 +#include "ofp-util.def" }; -const union ofp_action *actions_first(struct actions_iterator *, - const union ofp_action *, - size_t n_actions); -const union ofp_action *actions_next(struct actions_iterator *); + +int ofputil_decode_action(const union ofp_action *); +enum ofputil_action_code ofputil_decode_action_unsafe( + const union ofp_action *); + +int ofputil_action_code_from_name(const char *); + +void *ofputil_put_action(enum ofputil_action_code, struct ofpbuf *buf); + +/* For each OpenFlow action that has a corresponding action structure + * struct , this defines two functions: + * + * void ofputil_init_(struct *action); + * + * Initializes the parts of 'action' that identify it as having type + * and length 'sizeof *action' and zeros the rest. For actions that have + * variable length, the length used and cleared is that of struct . + * + * struct *ofputil_put_(struct ofpbuf *buf); + * + * Appends a new 'action', of length 'sizeof(struct )', to 'buf', + * initializes it with ofputil_init_(), and returns it. + */ +#define OFPAT_ACTION(ENUM, STRUCT, NAME) \ + void ofputil_init_##ENUM(struct STRUCT *); \ + struct STRUCT *ofputil_put_##ENUM(struct ofpbuf *); +#define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \ + void ofputil_init_##ENUM(struct STRUCT *); \ + struct STRUCT *ofputil_put_##ENUM(struct ofpbuf *); +#include "ofp-util.def" + +#define OFP_ACTION_ALIGN 8 /* Alignment of ofp_actions. */ + +static inline union ofp_action * +ofputil_action_next(const union ofp_action *a) +{ + return ((union ofp_action *) (void *) + ((uint8_t *) a + ntohs(a->header.len))); +} + +static inline bool +ofputil_action_is_valid(const union ofp_action *a, size_t n_actions) +{ + uint16_t len = ntohs(a->header.len); + return (!(len % OFP_ACTION_ALIGN) + && len >= sizeof *a + && len / sizeof *a <= n_actions); +} + +/* This macro is careful to check for actions with bad lengths. */ +#define OFPUTIL_ACTION_FOR_EACH(ITER, LEFT, ACTIONS, N_ACTIONS) \ + for ((ITER) = (ACTIONS), (LEFT) = (N_ACTIONS); \ + (LEFT) > 0 && ofputil_action_is_valid(ITER, LEFT); \ + ((LEFT) -= ntohs((ITER)->header.len) / sizeof(union ofp_action), \ + (ITER) = ofputil_action_next(ITER))) + +/* This macro does not check for actions with bad lengths. It should only be + * used with actions from trusted sources or with actions that have already + * been validated (e.g. with OFPUTIL_ACTION_FOR_EACH). */ +#define OFPUTIL_ACTION_FOR_EACH_UNSAFE(ITER, LEFT, ACTIONS, N_ACTIONS) \ + for ((ITER) = (ACTIONS), (LEFT) = (N_ACTIONS); \ + (LEFT) > 0; \ + ((LEFT) -= ntohs((ITER)->header.len) / sizeof(union ofp_action), \ + (ITER) = ofputil_action_next(ITER))) + int validate_actions(const union ofp_action *, size_t n_actions, const struct flow *, int max_ports); -bool action_outputs_to_port(const union ofp_action *, uint16_t port); +bool action_outputs_to_port(const union ofp_action *, ovs_be16 port); int ofputil_pull_actions(struct ofpbuf *, unsigned int actions_len, union ofp_action **, size_t *); + +bool ofputil_actions_equal(const union ofp_action *a, size_t n_a, + const union ofp_action *b, size_t n_b); +union ofp_action *ofputil_actions_clone(const union ofp_action *, size_t n); /* OpenFlow vendors. * @@ -352,6 +566,14 @@ get_ofp_err_code(int error) return error & 0xffff; } -struct ofpbuf *make_ofp_error_msg(int error, const struct ofp_header *); +struct ofpbuf *ofputil_encode_error_msg(int error, const struct ofp_header *); +int ofputil_decode_error_msg(const struct ofp_header *, size_t *payload_ofs); + +/* String versions of errors. */ +void ofputil_format_error(struct ds *, int error); +char *ofputil_error_to_string(int error); + +/* Handy utility for parsing flows and actions. */ +bool ofputil_parse_key_value(char **stringp, char **keyp, char **valuep); #endif /* ofp-util.h */