return 0;
}
-static int do_output(struct datapath *dp, struct sk_buff *skb, int out_port)
+static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port)
{
- struct vport *vport;
+ struct vport *vport = ovs_vport_rcu(dp, out_port);
- if (unlikely(!skb))
- return -ENOMEM;
-
- vport = ovs_vport_rcu(dp, out_port);
- if (unlikely(!vport)) {
+ if (likely(vport))
+ ovs_vport_send(vport, skb);
+ else
kfree_skb(skb);
- return -ENODEV;
- }
-
- ovs_vport_send(vport, skb);
- return 0;
}
static int output_userspace(struct datapath *dp, struct sk_buff *skb,
const struct nlattr *a;
int rem;
- BUG_ON(!OVS_CB(skb)->pkt_key);
-
upcall.cmd = OVS_PACKET_CMD_ACTION;
- upcall.key = OVS_CB(skb)->pkt_key;
upcall.userdata = NULL;
upcall.portid = 0;
skb_get(skb);
} else {
sample_skb = skb_clone(skb, GFP_ATOMIC);
+ if (!sample_skb)
+ /* Skip the sample action when out of memory. */
+ return 0;
}
/* Note that do_execute_actions() never consumes skb.
const struct nlattr *a)
{
struct sw_flow_key recirc_key;
- const struct vport *p = OVS_CB(skb)->input_vport;
uint32_t hash = OVS_CB(skb)->pkt_key->ovs_flow_hash;
int err;
- err = ovs_flow_extract(skb, p->port_no, &recirc_key);
+ err = ovs_flow_key_extract(skb, &recirc_key);
if (err) {
kfree_skb(skb);
return err;
a = nla_next(a, &rem)) {
int err = 0;
- if (prev_port != -1) {
- do_output(dp, skb_clone(skb, GFP_ATOMIC), prev_port);
+ if (unlikely(prev_port != -1)) {
+ struct sk_buff *out_skb = skb_clone(skb, GFP_ATOMIC);
+
+ if (out_skb)
+ do_output(dp, out_skb, prev_port);
+
prev_port = -1;
}
case OVS_ACTION_ATTR_RECIRC: {
struct sk_buff *recirc_skb;
- if (!last_action(a, rem))
- recirc_skb = skb_clone(skb, GFP_ATOMIC);
- else
- recirc_skb = skb;
+ if (last_action(a, rem))
+ return execute_recirc(dp, skb, a);
- err = execute_recirc(dp, recirc_skb, a);
+ /* Recirc action is the not the last action
+ * of the action list. */
+ recirc_skb = skb_clone(skb, GFP_ATOMIC);
- if (recirc_skb == skb)
- return err;
+ /* Skip the recirc action when out of memory, but
+ * continue on with the rest of the action list. */
+ if (recirc_skb)
+ err = execute_recirc(dp, recirc_skb, a);
break;
}
goto out_loop;
}
- if (!recirc)
- ovs_skb_init_inner_protocol(skb);
-
OVS_CB(skb)->tun_info = NULL;
error = do_execute_actions(dp, skb, acts->actions, acts->actions_len);