/*
* Distributed under the terms of the GNU GPL version 2.
- * Copyright (c) 2007, 2008, 2009, 2010 Nicira Networks.
+ * Copyright (c) 2007, 2008, 2009, 2010, 2011 Nicira Networks.
*
* Significant portions of this file may be copied from parts of the Linux
* kernel, by Linus Torvalds and others.
return NULL;
nh = ip_hdr(skb);
- nwaddr = nla_type(a) == ODPAT_SET_NW_SRC ? &nh->saddr : &nh->daddr;
+ nwaddr = nla_type(a) == ODP_ACTION_ATTR_SET_NW_SRC ? &nh->saddr : &nh->daddr;
check = get_l4_checksum(skb, key);
if (likely(check))
* supports those protocols.
*/
th = udp_hdr(skb);
- port = nla_type(a) == ODPAT_SET_TP_SRC ? &th->source : &th->dest;
+ port = nla_type(a) == ODP_ACTION_ATTR_SET_TP_SRC ? &th->source : &th->dest;
inet_proto_csum_replace2(check, skb, *port, nla_get_be16(a), 0);
*port = nla_get_be16(a);
kfree_skb(skb);
}
-static int output_control(struct datapath *dp, struct sk_buff *skb, u64 arg)
+static int output_control(struct datapath *dp, struct sk_buff *skb, u64 arg,
+ const struct sw_flow_key *key)
{
+ struct dp_upcall_info upcall;
+
skb = skb_clone(skb, GFP_ATOMIC);
if (!skb)
return -ENOMEM;
- return dp_output_control(dp, skb, _ODPL_ACTION_NR, arg);
+
+ upcall.cmd = ODP_PACKET_CMD_ACTION;
+ upcall.key = key;
+ upcall.userdata = arg;
+ upcall.sample_pool = 0;
+ upcall.actions = NULL;
+ upcall.actions_len = 0;
+ return dp_upcall(dp, skb, &upcall);
}
/* Execute a list of actions against 'skb'. */
}
switch (nla_type(a)) {
- case ODPAT_OUTPUT:
+ case ODP_ACTION_ATTR_OUTPUT:
prev_port = nla_get_u32(a);
break;
- case ODPAT_CONTROLLER:
- err = output_control(dp, skb, nla_get_u64(a));
+ case ODP_ACTION_ATTR_CONTROLLER:
+ err = output_control(dp, skb, nla_get_u64(a), key);
if (err) {
kfree_skb(skb);
return err;
}
break;
- case ODPAT_SET_TUNNEL:
+ case ODP_ACTION_ATTR_SET_TUNNEL:
OVS_CB(skb)->tun_id = nla_get_be64(a);
break;
- case ODPAT_SET_DL_TCI:
+ case ODP_ACTION_ATTR_SET_DL_TCI:
skb = modify_vlan_tci(dp, skb, key, a, rem);
if (IS_ERR(skb))
return PTR_ERR(skb);
break;
- case ODPAT_STRIP_VLAN:
+ case ODP_ACTION_ATTR_STRIP_VLAN:
skb = strip_vlan(skb);
break;
- case ODPAT_SET_DL_SRC:
+ case ODP_ACTION_ATTR_SET_DL_SRC:
skb = make_writable(skb, 0);
if (!skb)
return -ENOMEM;
memcpy(eth_hdr(skb)->h_source, nla_data(a), ETH_ALEN);
break;
- case ODPAT_SET_DL_DST:
+ case ODP_ACTION_ATTR_SET_DL_DST:
skb = make_writable(skb, 0);
if (!skb)
return -ENOMEM;
memcpy(eth_hdr(skb)->h_dest, nla_data(a), ETH_ALEN);
break;
- case ODPAT_SET_NW_SRC:
- case ODPAT_SET_NW_DST:
+ case ODP_ACTION_ATTR_SET_NW_SRC:
+ case ODP_ACTION_ATTR_SET_NW_DST:
skb = set_nw_addr(skb, key, a);
break;
- case ODPAT_SET_NW_TOS:
+ case ODP_ACTION_ATTR_SET_NW_TOS:
skb = set_nw_tos(skb, key, nla_get_u8(a));
break;
- case ODPAT_SET_TP_SRC:
- case ODPAT_SET_TP_DST:
+ case ODP_ACTION_ATTR_SET_TP_SRC:
+ case ODP_ACTION_ATTR_SET_TP_DST:
skb = set_tp_port(skb, key, a);
break;
- case ODPAT_SET_PRIORITY:
+ case ODP_ACTION_ATTR_SET_PRIORITY:
skb->priority = nla_get_u32(a);
break;
- case ODPAT_POP_PRIORITY:
+ case ODP_ACTION_ATTR_POP_PRIORITY:
skb->priority = priority;
break;
- case ODPAT_DROP_SPOOFED_ARP:
+ case ODP_ACTION_ATTR_DROP_SPOOFED_ARP:
if (unlikely(is_spoofed_arp(skb, key)))
goto exit;
break;
return 0;
}
-/* Send a copy of this packet up to the sFlow agent, along with extra
- * information about what happened to it. */
static void sflow_sample(struct datapath *dp, struct sk_buff *skb,
- const struct nlattr *a, u32 actions_len,
- struct vport *vport)
+ const struct sw_flow_key *key,
+ const struct nlattr *a, u32 actions_len)
{
- struct odp_sflow_sample_header *hdr;
- unsigned int hdrlen = sizeof(struct odp_sflow_sample_header);
struct sk_buff *nskb;
+ struct vport *p = OVS_CB(skb)->vport;
+ struct dp_upcall_info upcall;
+
+ if (unlikely(!p))
+ return;
- nskb = skb_copy_expand(skb, actions_len + hdrlen, 0, GFP_ATOMIC);
- if (!nskb)
+ atomic_inc(&p->sflow_pool);
+ if (net_random() >= dp->sflow_probability)
return;
- memcpy(__skb_push(nskb, actions_len), a, actions_len);
- hdr = (struct odp_sflow_sample_header*)__skb_push(nskb, hdrlen);
- hdr->actions_len = actions_len;
- hdr->sample_pool = atomic_read(&vport->sflow_pool);
- dp_output_control(dp, nskb, _ODPL_SFLOW_NR, 0);
+ nskb = skb_clone(skb, GFP_ATOMIC);
+ if (unlikely(!nskb))
+ return;
+
+ upcall.cmd = ODP_PACKET_CMD_SAMPLE;
+ upcall.key = key;
+ upcall.userdata = 0;
+ upcall.sample_pool = atomic_read(&p->sflow_pool);
+ upcall.actions = a;
+ upcall.actions_len = actions_len;
+ dp_upcall(dp, nskb, &upcall);
}
/* Execute a list of actions against 'skb'. */
const struct sw_flow_key *key,
const struct nlattr *actions, u32 actions_len)
{
- if (dp->sflow_probability) {
- struct vport *p = OVS_CB(skb)->vport;
- if (p) {
- atomic_inc(&p->sflow_pool);
- if (dp->sflow_probability == UINT_MAX ||
- net_random() < dp->sflow_probability)
- sflow_sample(dp, skb, actions, actions_len, p);
- }
- }
+ if (dp->sflow_probability)
+ sflow_sample(dp, skb, key, actions, actions_len);
OVS_CB(skb)->tun_id = 0;