#include <linux/types.h>
#include "forward.h"
#include "datapath.h"
+#include "openflow/nicira-ext.h"
#include "dp_act.h"
+#include "nx_msg.h"
#include "chain.h"
#include "flow.h"
if (v_code != ACT_VALIDATION_OK) {
dp_send_error_msg(chain->dp, sender, OFPET_BAD_ACTION, v_code,
ofm, ntohs(ofm->header.length));
- goto error;
+ goto error_free_flow;
}
/* Fill out flow. */
/* Act. */
error = chain_insert(chain, flow);
- if (error)
+ if (error == -ENOBUFS) {
+ dp_send_error_msg(chain->dp, sender, OFPET_FLOW_MOD_FAILED,
+ OFPFMFC_ALL_TABLES_FULL, ofm, ntohs(ofm->header.length));
+ goto error_free_flow;
+ } else if (error)
goto error_free_flow;
error = 0;
if (ntohl(ofm->buffer_id) != (uint32_t) -1) {
if (skb) {
struct sw_flow_key key;
flow_used(flow, skb);
+ dp_set_origin(chain->dp, ntohs(ofm->match.in_port), skb);
flow_extract(skb, ntohs(ofm->match.in_port), &key);
execute_actions(chain->dp, skb, &key, ofm->actions, actions_len, 0);
}
}
}
+static int
+recv_vendor(struct sw_chain *chain, const struct sender *sender,
+ const void *msg)
+{
+ const struct ofp_vendor_header *ovh = msg;
+
+ switch(ntohl(ovh->vendor))
+ {
+ case NX_VENDOR_ID:
+ return nx_recv_msg(chain, sender, msg);
+ default:
+ if (net_ratelimit())
+ printk("Uknown vendor: %#x\n", ntohl(ovh->vendor));
+ dp_send_error_msg(chain->dp, sender, OFPET_BAD_REQUEST,
+ OFPBRC_BAD_VENDOR, msg, ntohs(ovh->header.length));
+ return -EINVAL;
+ }
+}
+
/* 'msg', which is 'length' bytes long, was received across Netlink from
* 'sender'. Apply it to 'chain'. */
int
sizeof (struct ofp_header),
recv_hello,
},
+ [OFPT_ECHO_REQUEST] = {
+ sizeof (struct ofp_header),
+ recv_echo_request,
+ },
+ [OFPT_ECHO_REPLY] = {
+ sizeof (struct ofp_header),
+ recv_echo_reply,
+ },
+ [OFPT_VENDOR] = {
+ sizeof (struct ofp_vendor_header),
+ recv_vendor,
+ },
[OFPT_FEATURES_REQUEST] = {
sizeof (struct ofp_header),
recv_features_request,
[OFPT_PORT_MOD] = {
sizeof (struct ofp_port_mod),
recv_port_mod,
- },
- [OFPT_ECHO_REQUEST] = {
- sizeof (struct ofp_header),
- recv_echo_request,
- },
- [OFPT_ECHO_REPLY] = {
- sizeof (struct ofp_header),
- recv_echo_reply,
- },
+ }
};
struct ofp_header *oh;
OFPBRC_BAD_VERSION, msg, length);
return -EINVAL;
}
- if (ntohs(oh->length) > length)
+ if (ntohs(oh->length) != length) {
+ if (net_ratelimit())
+ printk("received message length wrong: %d/%d\n",
+ ntohs(oh->length), length);
return -EINVAL;
+ }
if (oh->type < ARRAY_SIZE(packets)) {
const struct openflow_packet *pkt = &packets[oh->type];
{
fwd_discard_all();
}
-