#include <linux/types.h>
#include "forward.h"
#include "datapath.h"
-#include "nicira-ext.h"
+#include "openflow/nicira-ext.h"
#include "dp_act.h"
#include "nx_msg.h"
#include "chain.h"
void fwd_port_input(struct sw_chain *chain, struct sk_buff *skb,
struct net_bridge_port *p)
{
+ WARN_ON_ONCE(skb_shared(skb));
+ WARN_ON_ONCE(skb->destructor);
if (run_flow_through_tables(chain, skb, p))
dp_output_control(chain->dp, skb, fwd_save_skb(skb),
chain->dp->miss_send_len,
{
const struct ofp_packet_out *opo = msg;
struct sk_buff *skb;
- struct vlan_ethhdr *mac;
- int nh_ofs;
uint16_t v_code;
struct sw_flow_key key;
size_t actions_len = ntohs(opo->actions_len);
/* FIXME? We don't reserve NET_IP_ALIGN or NET_SKB_PAD since
* we're just transmitting this raw without examining anything
* at those layers. */
- memcpy(skb_put(skb, data_len), (uint8_t *)opo->actions + actions_len,
- data_len);
-
- skb_set_mac_header(skb, 0);
- mac = vlan_eth_hdr(skb);
- if (likely(mac->h_vlan_proto != htons(ETH_P_8021Q)))
- nh_ofs = sizeof(struct ethhdr);
- else
- nh_ofs = sizeof(struct vlan_ethhdr);
- skb_set_network_header(skb, nh_ofs);
+ skb_put(skb, data_len);
+ skb_copy_to_linear_data(skb,
+ (uint8_t *)opo->actions + actions_len,
+ data_len);
+ skb_reset_mac_header(skb);
} else {
skb = retrieve_skb(ntohl(opo->buffer_id));
if (!skb)
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. */
flow->priority = flow->key.wildcards ? ntohs(ofm->priority) : -1;
flow->idle_timeout = ntohs(ofm->idle_timeout);
flow->hard_timeout = ntohs(ofm->hard_timeout);
- flow->used = jiffies;
- flow->init_time = jiffies;
+ flow->used = flow->created = get_jiffies_64();
flow->byte_count = 0;
flow->packet_count = 0;
+ flow->tcp_flags = 0;
+ flow->ip_tos = 0;
spin_lock_init(&flow->lock);
memcpy(flow->sf_acts->actions, ofm->actions, actions_len);
/* 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) {
} else if (command == OFPFC_DELETE) {
struct sw_flow_key key;
flow_extract_match(&key, &ofm->match);
- return chain_delete(chain, &key, 0, 0) ? 0 : -ESRCH;
+ return chain_delete(chain, &key, ofm->out_port, 0, 0) ? 0 : -ESRCH;
} else if (command == OFPFC_DELETE_STRICT) {
struct sw_flow_key key;
uint16_t priority;
flow_extract_match(&key, &ofm->match);
priority = key.wildcards ? ntohs(ofm->priority) : -1;
- return chain_delete(chain, &key, priority, 1) ? 0 : -ESRCH;
+ return chain_delete(chain, &key, ofm->out_port,
+ priority, 1) ? 0 : -ESRCH;
} else {
return -ENOTSUPP;
}
return nx_recv_msg(chain, sender, msg);
default:
if (net_ratelimit())
- printk("Uknown vendor: %#x\n", ntohl(ovh->vendor));
+ printk("unknown vendor: 0x%x\n", ntohl(ovh->vendor));
dp_send_error_msg(chain->dp, sender, OFPET_BAD_REQUEST,
- OFPBRC_BAD_VENDOR, msg, ovh->header.length);
+ OFPBRC_BAD_VENDOR, msg, ntohs(ovh->header.length));
return -EINVAL;
}
}
unsigned long int flags;
uint32_t id;
+ /* FIXME: Probably just need a skb_clone() here. */
+ skb = skb_copy(skb, GFP_ATOMIC);
+ if (!skb)
+ return -1;
+
spin_lock_irqsave(&buffer_lock, flags);
buffer_idx = (buffer_idx + 1) & PKT_BUFFER_MASK;
p = &buffers[buffer_idx];
* OVERWRITE_SECS old. */
if (time_before(jiffies, p->exp_jiffies)) {
spin_unlock_irqrestore(&buffer_lock, flags);
+ kfree_skb(skb);
return -1;
} else {
- /* Defer kfree_skb() until interrupts re-enabled. */
+ /* Defer kfree_skb() until interrupts re-enabled.
+ * FIXME: we only need to do that if it has a
+ * destructor, but it never should since we orphan
+ * sk_buffs on entry. */
old_skb = p->skb;
}
}
* special. */
if (++p->cookie >= (1u << PKT_COOKIE_BITS) - 1)
p->cookie = 0;
- skb_get(skb);
p->skb = skb;
p->exp_jiffies = jiffies + OVERWRITE_JIFFIES;
id = buffer_idx | (p->cookie << PKT_BUFFER_BITS);