From: Justin Pettit Date: Thu, 1 May 2008 00:38:03 +0000 (-0700) Subject: - Add support for OpenFlow error message type. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=66b5c90376a6a4b9f01258c0a452256f65d42d9e;p=openvswitch - Add support for OpenFlow error message type. - Ensure OpenFlow messages fit in 16-bit length field. --- diff --git a/datapath/datapath.c b/datapath/datapath.c index 7d2a44c0..cfebab80 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -46,6 +46,7 @@ #define BRIDGE_PORT_NO_FLOOD 0x00000001 #define UINT32_MAX 4294967295U +#define UINT16_MAX 65535 #define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) struct net_bridge_port { @@ -169,6 +170,13 @@ alloc_openflow_skb(struct datapath *dp, size_t openflow_len, uint8_t type, struct sk_buff *skb; int max_openflow_len; + if ((openflow_len + sizeof(struct ofp_header)) > UINT16_MAX) { + if (net_ratelimit()) + printk("alloc_openflow_skb: openflow message too large: %d\n", + openflow_len); + return NULL; + } + genl_len = nlmsg_total_size(GENL_HDRLEN + dp_genl_family.hdrsize); genl_len += nla_total_size(sizeof(uint32_t)); /* DP_GENL_A_DP_IDX */ genl_len += nla_total_size(openflow_len); /* DP_GENL_A_OPENFLOW */ @@ -804,6 +812,26 @@ dp_send_flow_expired(struct datapath *dp, struct sw_flow *flow) return send_openflow_skb(skb, NULL); } +int +dp_send_error_msg(struct datapath *dp, const struct sender *sender, + uint16_t type, uint16_t code, const uint8_t *data, size_t len) +{ + struct sk_buff *skb; + struct ofp_error_msg *oem; + + + oem = alloc_openflow_skb(dp, sizeof(*oem)+len, OFPT_ERROR_MSG, + sender, &skb); + if (!oem) + return -ENOMEM; + + oem->type = htons(type); + oem->code = htons(code); + memcpy(oem->data, data, len); + + return send_openflow_skb(skb, sender); +} + static void fill_flow_stats(struct ofp_flow_stats *ofs, struct sw_flow *flow, int table_idx) diff --git a/datapath/datapath.h b/datapath/datapath.h index 3e765e2c..76798ef8 100644 --- a/datapath/datapath.h +++ b/datapath/datapath.h @@ -65,16 +65,18 @@ struct sender { }; int dp_output_port(struct datapath *, struct sk_buff *, int out_port); -int dp_output_control(struct datapath *, struct sk_buff *, - uint32_t buffer_id, size_t max_len, int reason); +int dp_output_control(struct datapath *, struct sk_buff *, uint32_t, + size_t, int); int dp_set_origin(struct datapath *, uint16_t, struct sk_buff *); int dp_send_features_reply(struct datapath *, const struct sender *); int dp_send_config_reply(struct datapath *, const struct sender *); int dp_send_flow_expired(struct datapath *, struct sw_flow *); int dp_send_flow_stats(struct datapath *, const struct sender *, - const struct ofp_match *); + const struct ofp_match *); int dp_send_table_stats(struct datapath *, const struct sender *); int dp_send_port_stats(struct datapath *, const struct sender *); +int dp_send_error_msg(struct datapath *, const struct sender *, + uint16_t, uint16_t, const uint8_t *, size_t); int dp_update_port_flags(struct datapath *dp, const struct ofp_phy_port *opp); /* Should hold at least RCU read lock when calling */ diff --git a/include/openflow.h b/include/openflow.h index 648a3607..c8253e30 100644 --- a/include/openflow.h +++ b/include/openflow.h @@ -92,12 +92,13 @@ enum ofp_type { OFPT_TABLE, /* 9 Controller/switch message */ OFPT_PORT_MOD, /* 10 Controller/switch message */ OFPT_PORT_STATUS, /* 11 Async message */ - OFPT_FLOW_STATS_REQUEST, /* 12 Controller/switch message */ - OFPT_FLOW_STATS_REPLY, /* 13 Controller/switch message */ - OFPT_TABLE_STATS_REQUEST, /* 14 Controller/switch message */ - OFPT_TABLE_STATS_REPLY, /* 15 Controller/switch message */ - OFPT_PORT_STATS_REQUEST, /* 16 Controller/switch message */ - OFPT_PORT_STATS_REPLY /* 17 Controller/switch message */ + OFPT_ERROR_MSG, /* 12 Async message */ + OFPT_FLOW_STATS_REQUEST, /* 13 Controller/switch message */ + OFPT_FLOW_STATS_REPLY, /* 14 Controller/switch message */ + OFPT_TABLE_STATS_REQUEST, /* 15 Controller/switch message */ + OFPT_TABLE_STATS_REPLY, /* 16 Controller/switch message */ + OFPT_PORT_STATS_REQUEST, /* 17 Controller/switch message */ + OFPT_PORT_STATS_REPLY /* 18 Controller/switch message */ }; /* Header on all OpenFlow packets. */ @@ -358,6 +359,16 @@ struct ofp_flow_expired { uint64_t byte_count; }; +/* Error message (datapath -> controller). */ +struct ofp_error_msg { + struct ofp_header header; + + uint16_t type; + uint16_t code; + uint8_t data[0]; /* Variable-length data. Interpreted based + on the type and code. */ +}; + /* Statistics about flows that match the "match" field */ struct ofp_flow_stats { struct ofp_match match; /* Description of fields */ diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 7fa4cec0..8b2da7e0 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -410,6 +410,18 @@ ofp_print_flow_expired(struct ds *string, const void *oh, size_t len, ntohll(ofe->packet_count), ntohll(ofe->byte_count)); } +/* Pretty-print the OFPT_ERROR_MSG packet of 'len' bytes at 'oh' to 'string' + * at the given 'verbosity' level. */ +static void +ofp_print_error_msg(struct ds *string, const void *oh, size_t len, + int verbosity) +{ + const struct ofp_error_msg *oem = oh; + + ds_put_format(string, + " type%d code%d\n", ntohs(oem->type), ntohs(oem->code)); +} + /* Pretty-print the OFPT_PORT_STATUS packet of 'len' bytes at 'oh' to 'string' * at the given 'verbosity' level. */ static void @@ -591,6 +603,11 @@ static const struct openflow_packet packets[] = { sizeof (struct ofp_port_status), ofp_print_port_status }, + [OFPT_ERROR_MSG] = { + "error_msg", + sizeof (struct ofp_error_msg), + ofp_print_error_msg, + }, [OFPT_FLOW_STATS_REQUEST] = { "flow_stats_request", sizeof (struct ofp_flow_stats_request), diff --git a/switch/datapath.c b/switch/datapath.c index a3efa1a5..c3ae0991 100644 --- a/switch/datapath.c +++ b/switch/datapath.c @@ -627,6 +627,20 @@ send_flow_expired(struct datapath *dp, struct sw_flow *flow) send_openflow_buffer(dp, buffer, NULL); } +void +dp_send_error_msg(struct datapath *dp, const struct sender *sender, + uint16_t type, uint16_t code, const uint8_t *data, size_t len) +{ + struct buffer *buffer; + struct ofp_error_msg *oem; + oem = alloc_openflow_buffer(dp, sizeof(*oem)+len, OFPT_ERROR_MSG, + sender, &buffer); + oem->type = htons(type); + oem->code = htons(code); + memcpy(oem->data, data, len); + send_openflow_buffer(dp, buffer, sender); +} + static void fill_flow_stats(struct ofp_flow_stats *ofs, struct sw_flow *flow, int table_idx, time_t now)