Don't use designated array initializers in code compiled outside of Linux.
Needed for partner builds.
This commit is contained in:
1 parent
eb0341e711
commit
95204b0bf0
6 files changed
+215
-133
No files matched your search
+14
-6
@@ -41,11 +41,15 @@
|
||||
#include "util.h"
|
||||
|
||||
/* Logging importance levels. */
|
||||
#define VLOG_LEVELS \
|
||||
VLOG_LEVEL(EMER) \
|
||||
VLOG_LEVEL(ERR) \
|
||||
VLOG_LEVEL(WARN) \
|
||||
VLOG_LEVEL(DBG)
|
||||
enum vlog_level {
|
||||
VLL_EMER,
|
||||
VLL_ERR,
|
||||
VLL_WARN,
|
||||
VLL_DBG,
|
||||
#define VLOG_LEVEL(NAME) VLL_##NAME,
|
||||
VLOG_LEVELS
|
||||
#undef VLOG_LEVEL
|
||||
VLL_N_LEVELS
|
||||
};
|
||||
|
||||
@@ -53,9 +57,13 @@ const char *vlog_get_level_name(enum vlog_level);
|
||||
enum vlog_level vlog_get_level_val(const char *name);
|
||||
|
||||
/* Facilities that we can log to. */
|
||||
#define VLOG_FACILITIES \
|
||||
VLOG_FACILITY(SYSLOG) \
|
||||
VLOG_FACILITY(CONSOLE)
|
||||
enum vlog_facility {
|
||||
VLF_SYSLOG,
|
||||
VLF_CONSOLE,
|
||||
#define VLOG_FACILITY(NAME) VLF_##NAME,
|
||||
VLOG_FACILITIES
|
||||
#undef VLOG_FACILITY
|
||||
VLF_N_FACILITIES,
|
||||
VLF_ANY_FACILITY = -1
|
||||
};
|
||||
|
||||
+34
-16
@@ -65,13 +65,35 @@ struct option_class {
|
||||
size_t max_args; /* Maximum number of arguments. */
|
||||
};
|
||||
|
||||
static struct option_class classes[DHCP_N_OPTIONS] = {
|
||||
[0 ... 255] = {NULL, DHCP_ARG_UINT8, 0, SIZE_MAX},
|
||||
#define DHCP_OPT(NAME, CODE, TYPE, MIN, MAX) \
|
||||
[CODE] = {#NAME, DHCP_ARG_##TYPE, MIN, MAX},
|
||||
DHCP_OPTS
|
||||
static const struct option_class *
|
||||
get_option_class(int code)
|
||||
{
|
||||
static struct option_class classes[DHCP_N_OPTIONS];
|
||||
static bool init = false;
|
||||
if (!init) {
|
||||
int i;
|
||||
|
||||
init = true;
|
||||
#define DHCP_OPT(NAME, CODE, TYPE, MIN, MAX) \
|
||||
classes[CODE].name = #NAME; \
|
||||
classes[CODE].type = DHCP_ARG_##TYPE; \
|
||||
classes[CODE].min_args = MIN; \
|
||||
classes[CODE].max_args = MAX;
|
||||
DHCP_OPTS
|
||||
#undef DHCP_OPT
|
||||
};
|
||||
|
||||
for (i = 0; i < DHCP_N_OPTIONS; i++) {
|
||||
if (!classes[i].name) {
|
||||
classes[i].name = xasprintf("option-%d", i);
|
||||
classes[i].type = DHCP_ARG_UINT8;
|
||||
classes[i].min_args = 0;
|
||||
classes[i].max_args = SIZE_MAX;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(code >= 0 && code < DHCP_N_OPTIONS);
|
||||
return &classes[code];
|
||||
}
|
||||
|
||||
/* A single (bad) DHCP message can in theory dump out many, many log messages,
|
||||
* especially at high logging levels, so the burst size is set quite high
|
||||
@@ -409,18 +431,14 @@ put_duration(struct ds *ds, unsigned int duration)
|
||||
const char *
|
||||
dhcp_option_to_string(const struct dhcp_option *opt, int code, struct ds *ds)
|
||||
{
|
||||
struct option_class *class = &classes[code];
|
||||
const struct option_class *class = get_option_class(code);
|
||||
const struct arg_type *type = &types[class->type];
|
||||
size_t offset;
|
||||
const char *cp;
|
||||
|
||||
if (class->name) {
|
||||
const char *cp;
|
||||
for (cp = class->name; *cp; cp++) {
|
||||
unsigned char c = *cp;
|
||||
ds_put_char(ds, c == '_' ? '-' : tolower(c));
|
||||
}
|
||||
} else {
|
||||
ds_put_format(ds, "option-%d", code);
|
||||
for (cp = class->name; *cp; cp++) {
|
||||
unsigned char c = *cp;
|
||||
ds_put_char(ds, c == '_' ? '-' : tolower(c));
|
||||
}
|
||||
ds_put_char(ds, '=');
|
||||
|
||||
@@ -597,7 +615,7 @@ validate_options(struct dhcp_msg *msg)
|
||||
|
||||
for (code = 0; code < DHCP_N_OPTIONS; code++) {
|
||||
struct dhcp_option *opt = &msg->options[code];
|
||||
struct option_class *class = &classes[code];
|
||||
const struct option_class *class = get_option_class(code);
|
||||
struct arg_type *type = &types[class->type];
|
||||
if (opt->data) {
|
||||
size_t n_elems = opt->n / type->size;
|
||||
|
||||
+10
-7
@@ -111,6 +111,14 @@ lswitch_destroy(struct lswitch *sw)
|
||||
}
|
||||
}
|
||||
|
||||
static size_t
|
||||
min_size(uint8_t type)
|
||||
{
|
||||
return (type == OFPT_FEATURES_REPLY ? sizeof(struct ofp_switch_features)
|
||||
: type == OFPT_PACKET_IN ? offsetof (struct ofp_packet_in, data)
|
||||
: sizeof(struct ofp_header));
|
||||
}
|
||||
|
||||
/* Processes 'msg', which should be an OpenFlow received on 'rconn', according
|
||||
* to the learning switch state in 'sw'. The most likely result of processing
|
||||
* is that flow-setup and packet-out OpenFlow messages will be sent out on
|
||||
@@ -119,19 +127,14 @@ void
|
||||
lswitch_process_packet(struct lswitch *sw, struct rconn *rconn,
|
||||
const struct ofpbuf *msg)
|
||||
{
|
||||
static const size_t min_size[UINT8_MAX + 1] = {
|
||||
[0 ... UINT8_MAX] = sizeof (struct ofp_header),
|
||||
[OFPT_FEATURES_REPLY] = sizeof (struct ofp_switch_features),
|
||||
[OFPT_PACKET_IN] = offsetof (struct ofp_packet_in, data),
|
||||
};
|
||||
struct ofp_header *oh;
|
||||
|
||||
oh = msg->data;
|
||||
if (msg->size < min_size[oh->type]) {
|
||||
if (msg->size < min_size(oh->type)) {
|
||||
VLOG_WARN_RL(&rl,
|
||||
"%s: too short (%zu bytes) for type %"PRIu8" (min %zu)",
|
||||
rconn_get_name(rconn),
|
||||
msg->size, oh->type, min_size[oh->type]);
|
||||
msg->size, oh->type, min_size(oh->type));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+68
-29
@@ -847,25 +847,29 @@ print_stats(struct ds *string, int type, const void *body, size_t body_len,
|
||||
};
|
||||
|
||||
struct stats_type {
|
||||
int type;
|
||||
const char *name;
|
||||
struct stats_msg request;
|
||||
struct stats_msg reply;
|
||||
};
|
||||
|
||||
static const struct stats_type stats_types[] = {
|
||||
[OFPST_DESC] = {
|
||||
{
|
||||
OFPST_DESC,
|
||||
"description",
|
||||
{ 0, 0, NULL },
|
||||
{ 0, SIZE_MAX, ofp_desc_stats_reply },
|
||||
},
|
||||
[OFPST_FLOW] = {
|
||||
{
|
||||
OFPST_FLOW,
|
||||
"flow",
|
||||
{ sizeof(struct ofp_flow_stats_request),
|
||||
sizeof(struct ofp_flow_stats_request),
|
||||
ofp_flow_stats_request },
|
||||
{ 0, SIZE_MAX, ofp_flow_stats_reply },
|
||||
},
|
||||
[OFPST_AGGREGATE] = {
|
||||
{
|
||||
OFPST_AGGREGATE,
|
||||
"aggregate",
|
||||
{ sizeof(struct ofp_aggregate_stats_request),
|
||||
sizeof(struct ofp_aggregate_stats_request),
|
||||
@@ -874,21 +878,30 @@ print_stats(struct ds *string, int type, const void *body, size_t body_len,
|
||||
sizeof(struct ofp_aggregate_stats_reply),
|
||||
ofp_aggregate_stats_reply },
|
||||
},
|
||||
[OFPST_TABLE] = {
|
||||
{
|
||||
OFPST_TABLE,
|
||||
"table",
|
||||
{ 0, 0, NULL },
|
||||
{ 0, SIZE_MAX, ofp_table_stats_reply },
|
||||
},
|
||||
[OFPST_PORT] = {
|
||||
{
|
||||
OFPST_PORT,
|
||||
"port",
|
||||
{ 0, 0, NULL, },
|
||||
{ 0, SIZE_MAX, ofp_port_stats_reply },
|
||||
},
|
||||
[OFPST_SWITCH] = {
|
||||
{
|
||||
OFPST_SWITCH,
|
||||
"switch status",
|
||||
{ 0, 0, NULL, },
|
||||
{ 0, SIZE_MAX, switch_status_reply },
|
||||
},
|
||||
{
|
||||
-1,
|
||||
"unknown",
|
||||
{ 0, 0, NULL, },
|
||||
{ 0, 0, NULL, },
|
||||
},
|
||||
};
|
||||
|
||||
const struct stats_type *s;
|
||||
@@ -898,7 +911,11 @@ print_stats(struct ds *string, int type, const void *body, size_t body_len,
|
||||
ds_put_format(string, " ***unknown type %d***", type);
|
||||
return;
|
||||
}
|
||||
s = &stats_types[type];
|
||||
for (s = stats_types; s->type >= 0; s++) {
|
||||
if (s->type == type) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ds_put_format(string, " type=%d(%s)\n", type, s->name);
|
||||
|
||||
m = direction == REQUEST ? &s->request : &s->reply;
|
||||
@@ -963,88 +980,105 @@ ofp_echo(struct ds *string, const void *oh, size_t len, int verbosity)
|
||||
}
|
||||
|
||||
struct openflow_packet {
|
||||
uint8_t type;
|
||||
const char *name;
|
||||
size_t min_size;
|
||||
void (*printer)(struct ds *, const void *, size_t len, int verbosity);
|
||||
};
|
||||
|
||||
static const struct openflow_packet packets[] = {
|
||||
[OFPT_FEATURES_REQUEST] = {
|
||||
{
|
||||
OFPT_FEATURES_REQUEST,
|
||||
"features_request",
|
||||
sizeof (struct ofp_header),
|
||||
NULL,
|
||||
},
|
||||
[OFPT_FEATURES_REPLY] = {
|
||||
{
|
||||
OFPT_FEATURES_REPLY,
|
||||
"features_reply",
|
||||
sizeof (struct ofp_switch_features),
|
||||
ofp_print_switch_features,
|
||||
},
|
||||
[OFPT_GET_CONFIG_REQUEST] = {
|
||||
{
|
||||
OFPT_GET_CONFIG_REQUEST,
|
||||
"get_config_request",
|
||||
sizeof (struct ofp_header),
|
||||
NULL,
|
||||
},
|
||||
[OFPT_GET_CONFIG_REPLY] = {
|
||||
{
|
||||
OFPT_GET_CONFIG_REPLY,
|
||||
"get_config_reply",
|
||||
sizeof (struct ofp_switch_config),
|
||||
ofp_print_switch_config,
|
||||
},
|
||||
[OFPT_SET_CONFIG] = {
|
||||
{
|
||||
OFPT_SET_CONFIG,
|
||||
"set_config",
|
||||
sizeof (struct ofp_switch_config),
|
||||
ofp_print_switch_config,
|
||||
},
|
||||
[OFPT_PACKET_IN] = {
|
||||
{
|
||||
OFPT_PACKET_IN,
|
||||
"packet_in",
|
||||
offsetof(struct ofp_packet_in, data),
|
||||
ofp_packet_in,
|
||||
},
|
||||
[OFPT_PACKET_OUT] = {
|
||||
{
|
||||
OFPT_PACKET_OUT,
|
||||
"packet_out",
|
||||
sizeof (struct ofp_packet_out),
|
||||
ofp_packet_out,
|
||||
},
|
||||
[OFPT_FLOW_MOD] = {
|
||||
{
|
||||
OFPT_FLOW_MOD,
|
||||
"flow_mod",
|
||||
sizeof (struct ofp_flow_mod),
|
||||
ofp_print_flow_mod,
|
||||
},
|
||||
[OFPT_FLOW_EXPIRED] = {
|
||||
{
|
||||
OFPT_FLOW_EXPIRED,
|
||||
"flow_expired",
|
||||
sizeof (struct ofp_flow_expired),
|
||||
ofp_print_flow_expired,
|
||||
},
|
||||
[OFPT_PORT_MOD] = {
|
||||
{
|
||||
OFPT_PORT_MOD,
|
||||
"port_mod",
|
||||
sizeof (struct ofp_port_mod),
|
||||
NULL,
|
||||
},
|
||||
[OFPT_PORT_STATUS] = {
|
||||
{
|
||||
OFPT_PORT_STATUS,
|
||||
"port_status",
|
||||
sizeof (struct ofp_port_status),
|
||||
ofp_print_port_status
|
||||
},
|
||||
[OFPT_ERROR_MSG] = {
|
||||
{
|
||||
OFPT_ERROR_MSG,
|
||||
"error_msg",
|
||||
sizeof (struct ofp_error_msg),
|
||||
ofp_print_error_msg,
|
||||
},
|
||||
[OFPT_STATS_REQUEST] = {
|
||||
{
|
||||
OFPT_STATS_REQUEST,
|
||||
"stats_request",
|
||||
sizeof (struct ofp_stats_request),
|
||||
ofp_stats_request,
|
||||
},
|
||||
[OFPT_STATS_REPLY] = {
|
||||
{
|
||||
OFPT_STATS_REPLY,
|
||||
"stats_reply",
|
||||
sizeof (struct ofp_stats_reply),
|
||||
ofp_stats_reply,
|
||||
},
|
||||
[OFPT_ECHO_REQUEST] = {
|
||||
{
|
||||
OFPT_ECHO_REQUEST,
|
||||
"echo_request",
|
||||
sizeof (struct ofp_header),
|
||||
ofp_echo,
|
||||
},
|
||||
[OFPT_ECHO_REPLY] = {
|
||||
{
|
||||
OFPT_ECHO_REPLY,
|
||||
"echo_reply",
|
||||
sizeof (struct ofp_header),
|
||||
ofp_echo,
|
||||
@@ -1070,14 +1104,19 @@ ofp_to_string(const void *oh_, size_t len, int verbosity)
|
||||
ds_put_format(&string, "Bad OpenFlow version %"PRIu8":\n", oh->version);
|
||||
ds_put_hex_dump(&string, oh, len, 0, true);
|
||||
return ds_cstr(&string);
|
||||
} else if (oh->type >= ARRAY_SIZE(packets) || !packets[oh->type].name) {
|
||||
ds_put_format(&string, "Unknown OpenFlow packet type %"PRIu8":\n",
|
||||
oh->type);
|
||||
ds_put_hex_dump(&string, oh, len, 0, true);
|
||||
return ds_cstr(&string);
|
||||
}
|
||||
|
||||
pkt = &packets[oh->type];
|
||||
for (pkt = packets; ; pkt++) {
|
||||
if (pkt >= &packets[ARRAY_SIZE(packets)]) {
|
||||
ds_put_format(&string, "Unknown OpenFlow packet type %"PRIu8":\n",
|
||||
oh->type);
|
||||
ds_put_hex_dump(&string, oh, len, 0, true);
|
||||
return ds_cstr(&string);
|
||||
} else if (oh->type == pkt->type) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ds_put_format(&string, "%s (xid=0x%"PRIx32"):", pkt->name, oh->xid);
|
||||
|
||||
if (ntohs(oh->length) > len)
|
||||
|
||||
+15
-13
@@ -51,16 +51,16 @@
|
||||
|
||||
/* Name for each logging level. */
|
||||
static const char *level_names[VLL_N_LEVELS] = {
|
||||
[VLL_EMER] = "EMER",
|
||||
[VLL_ERR] = "ERR",
|
||||
[VLL_WARN] = "WARN",
|
||||
[VLL_DBG] = "DBG",
|
||||
#define VLOG_LEVEL(NAME) #NAME,
|
||||
VLOG_LEVELS
|
||||
#undef VLOG_LEVEL
|
||||
};
|
||||
|
||||
/* Name for each logging facility. */
|
||||
static const char *facility_names[VLF_N_FACILITIES] = {
|
||||
[VLF_CONSOLE] = "console",
|
||||
[VLF_SYSLOG] = "syslog",
|
||||
#define VLOG_FACILITY(NAME) #NAME,
|
||||
VLOG_FACILITIES
|
||||
#undef VLOG_FACILITY
|
||||
};
|
||||
|
||||
/* Name for each logging module */
|
||||
@@ -341,18 +341,20 @@ vlog_valist(enum vlog_module module, enum vlog_level level,
|
||||
}
|
||||
|
||||
if (log_syslog) {
|
||||
static const int syslog_levels[VLL_N_LEVELS] = {
|
||||
[VLL_EMER] = LOG_ALERT,
|
||||
[VLL_ERR] = LOG_ERR,
|
||||
[VLL_WARN] = LOG_WARNING,
|
||||
[VLL_DBG] = LOG_DEBUG,
|
||||
};
|
||||
int syslog_level = LOG_ALERT;
|
||||
char *save_ptr = NULL;
|
||||
char *line;
|
||||
|
||||
switch (level) {
|
||||
case VLL_EMER: syslog_level = LOG_ALERT; break;
|
||||
case VLL_ERR: syslog_level = LOG_ERR; break;
|
||||
case VLL_WARN: syslog_level = LOG_WARNING; break;
|
||||
case VLL_DBG: syslog_level = LOG_DEBUG; break;
|
||||
case VLL_N_LEVELS: NOT_REACHED();
|
||||
}
|
||||
for (line = strtok_r(&s.string[time_len], "\n", &save_ptr); line;
|
||||
line = strtok_r(NULL, "\n", &save_ptr)) {
|
||||
syslog(syslog_levels[level], "%s", line);
|
||||
syslog(syslog_level, "%s", line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+74
-62
@@ -1449,6 +1449,9 @@ static void port_stats_done(void *state)
|
||||
}
|
||||
|
||||
struct stats_type {
|
||||
/* Value for 'type' member of struct ofp_stats_request. */
|
||||
int type;
|
||||
|
||||
/* Minimum and maximum acceptable number of bytes in body member of
|
||||
* struct ofp_stats_request. */
|
||||
size_t min_body, max_body;
|
||||
@@ -1473,35 +1476,40 @@ struct stats_type {
|
||||
};
|
||||
|
||||
static const struct stats_type stats[] = {
|
||||
[OFPST_DESC] = {
|
||||
{
|
||||
OFPST_DESC,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
desc_stats_dump,
|
||||
NULL
|
||||
},
|
||||
[OFPST_FLOW] = {
|
||||
{
|
||||
OFPST_FLOW,
|
||||
sizeof(struct ofp_flow_stats_request),
|
||||
sizeof(struct ofp_flow_stats_request),
|
||||
flow_stats_init,
|
||||
flow_stats_dump,
|
||||
flow_stats_done
|
||||
},
|
||||
[OFPST_AGGREGATE] = {
|
||||
{
|
||||
OFPST_AGGREGATE,
|
||||
sizeof(struct ofp_aggregate_stats_request),
|
||||
sizeof(struct ofp_aggregate_stats_request),
|
||||
aggregate_stats_init,
|
||||
aggregate_stats_dump,
|
||||
aggregate_stats_done
|
||||
},
|
||||
[OFPST_TABLE] = {
|
||||
{
|
||||
OFPST_TABLE,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
table_stats_dump,
|
||||
NULL
|
||||
},
|
||||
[OFPST_PORT] = {
|
||||
{
|
||||
OFPST_PORT,
|
||||
0,
|
||||
0,
|
||||
port_stats_init,
|
||||
@@ -1532,7 +1540,7 @@ stats_dump(struct datapath *dp, void *cb_)
|
||||
|
||||
osr = make_openflow_reply(sizeof *osr, OFPT_STATS_REPLY, &cb->sender,
|
||||
&buffer);
|
||||
osr->type = htons(cb->s - stats);
|
||||
osr->type = htons(cb->s->type);
|
||||
osr->flags = 0;
|
||||
|
||||
err = cb->s->dump(dp, cb->state, buffer);
|
||||
@@ -1572,21 +1580,27 @@ recv_stats_request(struct datapath *dp, const struct sender *sender,
|
||||
{
|
||||
const struct ofp_stats_request *rq = oh;
|
||||
size_t rq_len = ntohs(rq->header.length);
|
||||
const struct stats_type *st;
|
||||
struct stats_dump_cb *cb;
|
||||
int type, body_len;
|
||||
int err;
|
||||
|
||||
type = ntohs(rq->type);
|
||||
if (type >= ARRAY_SIZE(stats) || !stats[type].dump) {
|
||||
VLOG_WARN_RL(&rl, "received stats request of unknown type %d", type);
|
||||
return -EINVAL;
|
||||
for (st = stats; ; st++) {
|
||||
if (st >= &stats[ARRAY_SIZE(stats)]) {
|
||||
VLOG_WARN_RL(&rl, "received stats request of unknown type %d",
|
||||
type);
|
||||
return -EINVAL;
|
||||
} else if (type == st->type) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cb = xmalloc(sizeof *cb);
|
||||
cb->done = false;
|
||||
cb->rq = xmemdup(rq, rq_len);
|
||||
cb->sender = *sender;
|
||||
cb->s = &stats[type];
|
||||
cb->s = st;
|
||||
cb->state = NULL;
|
||||
|
||||
body_len = rq_len - offsetof(struct ofp_stats_request, body);
|
||||
@@ -1636,65 +1650,63 @@ int
|
||||
fwd_control_input(struct datapath *dp, const struct sender *sender,
|
||||
const void *msg, size_t length)
|
||||
{
|
||||
struct openflow_packet {
|
||||
size_t min_size;
|
||||
int (*handler)(struct datapath *, const struct sender *, const void *);
|
||||
};
|
||||
|
||||
static const struct openflow_packet packets[] = {
|
||||
[OFPT_FEATURES_REQUEST] = {
|
||||
sizeof (struct ofp_header),
|
||||
recv_features_request,
|
||||
},
|
||||
[OFPT_GET_CONFIG_REQUEST] = {
|
||||
sizeof (struct ofp_header),
|
||||
recv_get_config_request,
|
||||
},
|
||||
[OFPT_SET_CONFIG] = {
|
||||
sizeof (struct ofp_switch_config),
|
||||
recv_set_config,
|
||||
},
|
||||
[OFPT_PACKET_OUT] = {
|
||||
sizeof (struct ofp_packet_out),
|
||||
recv_packet_out,
|
||||
},
|
||||
[OFPT_FLOW_MOD] = {
|
||||
sizeof (struct ofp_flow_mod),
|
||||
recv_flow,
|
||||
},
|
||||
[OFPT_PORT_MOD] = {
|
||||
sizeof (struct ofp_port_mod),
|
||||
recv_port_mod,
|
||||
},
|
||||
[OFPT_STATS_REQUEST] = {
|
||||
sizeof (struct ofp_stats_request),
|
||||
recv_stats_request,
|
||||
},
|
||||
[OFPT_ECHO_REQUEST] = {
|
||||
sizeof (struct ofp_header),
|
||||
recv_echo_request,
|
||||
},
|
||||
[OFPT_ECHO_REPLY] = {
|
||||
sizeof (struct ofp_header),
|
||||
recv_echo_reply,
|
||||
},
|
||||
};
|
||||
|
||||
const struct openflow_packet *pkt;
|
||||
int (*handler)(struct datapath *, const struct sender *, const void *);
|
||||
struct ofp_header *oh;
|
||||
size_t min_size;
|
||||
|
||||
/* Check encapsulated length. */
|
||||
oh = (struct ofp_header *) msg;
|
||||
assert(oh->version == OFP_VERSION);
|
||||
if (oh->type >= ARRAY_SIZE(packets) || ntohs(oh->length) > length)
|
||||
if (ntohs(oh->length) > length) {
|
||||
return -EINVAL;
|
||||
}
|
||||
assert(oh->version == OFP_VERSION);
|
||||
|
||||
pkt = &packets[oh->type];
|
||||
if (!pkt->handler)
|
||||
/* Figure out how to handle it. */
|
||||
switch (oh->type) {
|
||||
case OFPT_FEATURES_REQUEST:
|
||||
min_size = sizeof(struct ofp_header);
|
||||
handler = recv_features_request;
|
||||
break;
|
||||
case OFPT_GET_CONFIG_REQUEST:
|
||||
min_size = sizeof(struct ofp_header);
|
||||
handler = recv_get_config_request;
|
||||
break;
|
||||
case OFPT_SET_CONFIG:
|
||||
min_size = sizeof(struct ofp_switch_config);
|
||||
handler = recv_set_config;
|
||||
break;
|
||||
case OFPT_PACKET_OUT:
|
||||
min_size = sizeof(struct ofp_packet_out);
|
||||
handler = recv_packet_out;
|
||||
break;
|
||||
case OFPT_FLOW_MOD:
|
||||
min_size = sizeof(struct ofp_flow_mod);
|
||||
handler = recv_flow;
|
||||
break;
|
||||
case OFPT_PORT_MOD:
|
||||
min_size = sizeof(struct ofp_port_mod);
|
||||
handler = recv_port_mod;
|
||||
break;
|
||||
case OFPT_STATS_REQUEST:
|
||||
min_size = sizeof(struct ofp_stats_request);
|
||||
handler = recv_stats_request;
|
||||
break;
|
||||
case OFPT_ECHO_REQUEST:
|
||||
min_size = sizeof(struct ofp_header);
|
||||
handler = recv_echo_request;
|
||||
break;
|
||||
case OFPT_ECHO_REPLY:
|
||||
min_size = sizeof(struct ofp_header);
|
||||
handler = recv_echo_reply;
|
||||
break;
|
||||
default:
|
||||
return -ENOSYS;
|
||||
if (length < pkt->min_size)
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return pkt->handler(dp, sender, msg);
|
||||
/* Handle it. */
|
||||
if (length < min_size)
|
||||
return -EFAULT;
|
||||
return handler(dp, sender, msg);
|
||||
}
|
||||
|
||||
/* Packet buffering. */
|
||||
|
||||
Reference in new issue
Block a user