This looks great already. Some minor stuff. On 03/08/2014 03:04 AM, Alex Wang wrote:
@@ -1459,7 +1459,7 @@ static const struct nla_policy vport_policy[OVS_VPORT_ATTR_MAX + 1] = { [OVS_VPORT_ATTR_STATS] = { .len = sizeof(struct ovs_vport_stats) }, [OVS_VPORT_ATTR_PORT_NO] = { .type = NLA_U32 }, [OVS_VPORT_ATTR_TYPE] = { .type = NLA_U32 }, - [OVS_VPORT_ATTR_UPCALL_PID] = { .type = NLA_U32 }, + [OVS_VPORT_ATTR_UPCALL_PID] = { .type = NLA_UNSPEC }, [OVS_VPORT_ATTR_OPTIONS] = { .type = NLA_NESTED }, };
I can understand that you want to change the policy to reflect the change in the extended format. Technically, staying at NLA_U32 would result in the same as you have now: enforce a minimal payload size of 4 bytes. This change might raise eyebrows though in the push to netdev as it looks like an ABI breakage without closer inspection.
+int ovs_vport_set_upcall_portids(struct vport *vport, struct nlattr *ids) +{ + struct vport_portids *old, *vport_portids; + + if (!nla_len(ids) || nla_len(ids) % sizeof(u32)) + return -EINVAL;
This may crash if OVS_VPORT_ATTR_UPCALL_PID is not provided and ids becomes NULL since you removed the if (a[OVS_VPORT_ATTR_UPCALL_PID]) in ovs_vport_cmd_set().
+/** + * ovs_vport_get_upcall_portids - get the upcall_portids of @vport. + * + * @vport: vport from which to retrieve the portids. + * @skb: sk_buff where portids should be appended. + * + * Retrieves the configuration of the given vport, appending the + * %OVS_VPORT_ATTR_UPCALL_PID attribute which is the array of upcall + * portids to @skb. + * + * Returns 0 if successful, -EMSGSIZE if @skb has insufficient room. + * If an error occurs, @skb is left unmodified. Must be called with + * rcu_read_lock. + */ +int ovs_vport_get_upcall_portids(const struct vport *vport, + struct sk_buff *skb) +{ + struct vport_portids *ids; + int err = 0; + + ids = rcu_dereference_ovsl(vport->upcall_portids); + + if (vport->dp->user_features & OVS_DP_F_VPORT_PIDS) { + if (nla_put(skb, OVS_VPORT_ATTR_UPCALL_PID, + ids->n_ids * sizeof(u32), (void *) ids->ids)) + err = -EMSGSIZE; + + } else { + if (nla_put_u32(skb, OVS_VPORT_ATTR_UPCALL_PID, + *ids->ids)) + err = -EMSGSIZE; + } + + return err;
If you want to reduce code size here, you can simply return nla_put*() and get rid of the additional branching since these functions already return -EMSGSIZE.
+u32 ovs_vport_find_portid(const struct vport *p, struct sk_buff *skb) +{ + struct vport_portids *ids; + + ids = rcu_dereference_ovsl(p->upcall_portids); + + if (ids->n_ids == 1 && *ids->ids == 0) + return 0; + + return ids->ids[skb_get_rxhash(skb) % ids->n_ids];
I have some dislike for the division here. I realize this is the slow path but no point in adding it if it can be avoided. Worst case, this is exploitable in a DoS scenario. One idea here might be to look at RPS and see how it avoided this using flow masks, see store_rps_dev_flow_table_cnt(). _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev