}
static int execute_recirc(struct datapath *dp, struct sk_buff *skb,
- struct sw_flow_key *key, const struct nlattr *a, int rem)
+ struct sw_flow_key *key,
+ const struct nlattr *a, int rem)
{
struct deferred_action *da;
err = ovs_flow_key_update(skb, key);
if (err)
return err;
-
}
BUG_ON(!is_flow_key_valid(key));
do {
struct deferred_action *da = action_fifo_get(fifo);
struct sk_buff *skb = da->skb;
+ struct sw_flow_key *key = &da->pkt_key;
const struct nlattr *actions = da->actions;
if (actions)
- do_execute_actions(dp, skb, &da->pkt_key, actions,
+ do_execute_actions(dp, skb, key, actions,
nla_len(actions));
else
- ovs_dp_process_packet(skb, &da->pkt_key);
+ ovs_dp_process_packet(skb, key);
} while (!action_fifo_is_empty(fifo));
/* Reset FIFO for the next packet. */
/* Execute a list of actions against 'skb'. */
int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb,
- struct sw_flow_key *key,
- const struct sw_flow_actions *acts)
+ const struct sw_flow_actions *acts,
+ struct sw_flow_key *key)
{
int level = this_cpu_read(exec_actions_level);
int err;
}
this_cpu_inc(exec_actions_level);
-
- err = do_execute_actions(dp, skb, key, acts->actions, acts->actions_len);
+ err = do_execute_actions(dp, skb, key,
+ acts->actions, acts->actions_len);
if (!level)
process_deferred_actions(dp);
const struct sw_flow_key *,
const struct dp_upcall_info *);
static int queue_userspace_packet(struct datapath *dp, struct sk_buff *,
- const struct sw_flow_key *key,
+ const struct sw_flow_key *,
const struct dp_upcall_info *);
/* Must be called with rcu_read_lock. */
upcall.userdata = NULL;
upcall.portid = ovs_vport_find_upcall_portid(p, skb);
upcall.egress_tun_info = NULL;
-
error = ovs_dp_upcall(dp, skb, key, &upcall);
if (unlikely(error))
kfree_skb(skb);
else
consume_skb(skb);
-
stats_counter = &stats->n_missed;
goto out;
}
ovs_flow_stats_update(flow, key->tp.flags, skb);
-
sf_acts = rcu_dereference(flow->sf_acts);
- ovs_execute_actions(dp, skb, key, sf_acts);
+ ovs_execute_actions(dp, skb, sf_acts, key);
+
stats_counter = &stats->n_hit;
out:
out:
if (err)
skb_tx_error(skb);
-
kfree_skb(user_skb);
kfree_skb(nskb);
return err;
sf_acts = rcu_dereference(flow->sf_acts);
local_bh_disable();
- err = ovs_execute_actions(dp, packet, &flow->key, sf_acts);
+ err = ovs_execute_actions(dp, packet, sf_acts, &flow->key);
local_bh_enable();
rcu_read_unlock();
if (!nla)
return -EMSGSIZE;
- err = ovs_nla_put_flow(&flow->unmasked_key,
- &flow->unmasked_key, skb);
+ err = ovs_nla_put_flow(&flow->unmasked_key, &flow->unmasked_key, skb);
if (err)
return err;
+
nla_nest_end(skb, nla);
/* Fill flow mask. */
err = ovs_nla_put_flow(&flow->key, &flow->mask->key, skb);
if (err)
return err;
- nla_nest_end(skb, nla);
+ nla_nest_end(skb, nla);
return 0;
}
struct ovs_header *ovs_header;
int err;
- ovs_header = genlmsg_put(skb, portid, seq, &dp_flow_genl_family, flags, cmd);
+ ovs_header = genlmsg_put(skb, portid, seq, &dp_flow_genl_family,
+ flags, cmd);
if (!ovs_header)
return -EMSGSIZE;
+
ovs_header->dp_ifindex = dp_ifindex;
err = ovs_flow_cmd_fill_match(flow, skb);
return NULL;
skb = genlmsg_new_unicast(ovs_flow_cmd_msg_size(acts), info, GFP_KERNEL);
-
if (!skb)
return ERR_PTR(-ENOMEM);
}
/* Called with ovs_mutex. */
-static struct sk_buff *ovs_flow_cmd_build_info(struct datapath *dp,
- const struct sw_flow *flow,
+static struct sk_buff *ovs_flow_cmd_build_info(const struct sw_flow *flow,
int dp_ifindex,
struct genl_info *info, u8 cmd,
bool always)
/* Must have key and actions. */
error = -EINVAL;
if (!a[OVS_FLOW_ATTR_KEY]) {
- OVS_NLERR(log, "Flow key attribute not present in new flow.");
+ OVS_NLERR(log, "Flow key attr not present in new flow.");
goto error;
}
if (!a[OVS_FLOW_ATTR_ACTIONS]) {
- OVS_NLERR(log,
- "Flow actions attribute not present in new flow.");
+ OVS_NLERR(log, "Flow actions attr not present in new flow.");
goto error;
}
error = ovs_nla_copy_actions(a[OVS_FLOW_ATTR_ACTIONS], &new_flow->key,
&acts, log);
if (error) {
- OVS_NLERR(
- log,
- "Flow actions may not be safe on all matching packets."
- );
+ OVS_NLERR(log, "Flow actions may not be safe on all matching packets.");
goto err_kfree_flow;
}
error = ovs_nla_copy_actions(a, &masked_key, &acts, log);
if (error) {
OVS_NLERR(log,
- "Actions may not be safe on all matching packets.");
+ "Actions may not be safe on all matching packets");
return ERR_PTR(error);
}
}
} else {
/* Could not alloc without acts before locking. */
- reply = ovs_flow_cmd_build_info(dp, flow,
- ovs_header->dp_ifindex,
+ reply = ovs_flow_cmd_build_info(flow, ovs_header->dp_ifindex,
info, OVS_FLOW_CMD_NEW, false);
if (unlikely(IS_ERR(reply))) {
error = PTR_ERR(reply);
ovs_notify(&dp_flow_genl_family, &ovs_dp_flow_multicast_group, reply, info);
if (old_acts)
ovs_nla_free_flow_actions(old_acts);
+
return 0;
err_unlock_ovs:
goto unlock;
}
- reply = ovs_flow_cmd_build_info(dp, flow, ovs_header->dp_ifindex, info,
+ reply = ovs_flow_cmd_build_info(flow, ovs_header->dp_ifindex, info,
OVS_FLOW_CMD_NEW, true);
if (IS_ERR(reply)) {
err = PTR_ERR(reply);
err = -ENODEV;
goto unlock;
}
+
if (unlikely(!a[OVS_FLOW_ATTR_KEY])) {
err = ovs_flow_tbl_flush(&dp->table);
goto unlock;
}
+
flow = ovs_flow_tbl_lookup_exact(&dp->table, &match);
if (unlikely(!flow)) {
err = -ENOENT;
if (likely(reply)) {
if (likely(!IS_ERR(reply))) {
- rcu_read_lock(); /* Keep RCU checker happy. */
- err = ovs_flow_cmd_fill_info(flow,
- ovs_header->dp_ifindex,
+ rcu_read_lock(); /*To keep RCU checker happy. */
+ err = ovs_flow_cmd_fill_info(flow, ovs_header->dp_ifindex,
reply, info->snd_portid,
info->snd_seq, 0,
OVS_FLOW_CMD_DEL);
ovs_net = net_generic(ovs_dp_get_net(dp), ovs_net_id);
list_add_tail_rcu(&dp->list_node, &ovs_net->dps);
-
ovs_unlock();
ovs_notify(&dp_datapath_genl_family, &ovs_dp_datapath_multicast_group, reply, info);
BUG_ON(err < 0);
__dp_destroy(dp);
-
ovs_unlock();
+
ovs_notify(&dp_datapath_genl_family, &ovs_dp_datapath_multicast_group, reply, info);
return 0;
err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid,
info->snd_seq, 0, OVS_DP_CMD_NEW);
BUG_ON(err < 0);
-
ovs_unlock();
+
ovs_notify(&dp_datapath_genl_family, &ovs_dp_datapath_multicast_group, reply, info);
return 0;
}
if (a[OVS_VPORT_ATTR_UPCALL_PID]) {
- err = ovs_vport_set_upcall_portids(vport,
- a[OVS_VPORT_ATTR_UPCALL_PID]);
+ struct nlattr *ids = a[OVS_VPORT_ATTR_UPCALL_PID];
+
+ err = ovs_vport_set_upcall_portids(vport, ids);
if (err)
goto exit_unlock_free;
}
#include "vlan.h"
#include "vport.h"
-#define DP_MAX_PORTS USHRT_MAX
-#define DP_VPORT_HASH_BUCKETS 1024
+#define DP_MAX_PORTS USHRT_MAX
+#define DP_VPORT_HASH_BUCKETS 1024
#define SAMPLE_ACTION_DEPTH 3
* @cmd: One of %OVS_PACKET_CMD_*.
* @userdata: If nonnull, its variable-length value is passed to userspace as
* %OVS_PACKET_ATTR_USERDATA.
- * @portid: Netlink PID to which packet should be sent. If @portid is 0 then no
- * packet is sent and the packet is accounted in the datapath's @n_lost
+ * @portid: Netlink portid to which packet should be sent. If @portid is 0
+ * then no packet is sent and the packet is accounted in the datapath's @n_lost
* counter.
* @egress_tun_info: If nonnull, becomes %OVS_PACKET_ATTR_EGRESS_TUN_KEY.
*/
struct dp_upcall_info {
+ const struct ovs_tunnel_info *egress_tun_info;
const struct nlattr *userdata;
u32 portid;
u8 cmd;
- const struct ovs_tunnel_info *egress_tun_info;
};
/**
*/
struct ovs_net {
struct list_head dps;
- struct vport_net vport_net;
struct work_struct dp_notify_work;
+ struct vport_net vport_net;
};
extern int ovs_net_id;
extern struct genl_family dp_vport_genl_family;
extern struct genl_multicast_group ovs_dp_vport_multicast_group;
-void ovs_dp_process_packet(struct sk_buff *, struct sw_flow_key *key);
+void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key);
void ovs_dp_detach_port(struct vport *);
int ovs_dp_upcall(struct datapath *, struct sk_buff *,
const struct sw_flow_key *, const struct dp_upcall_info *);
const char *ovs_dp_name(const struct datapath *dp);
-struct sk_buff *ovs_vport_cmd_build_info(struct vport *, u32 portid, u32 seq,
+struct sk_buff *ovs_vport_cmd_build_info(struct vport *, u32 pid, u32 seq,
u8 cmd);
int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb,
- struct sw_flow_key *key,
- const struct sw_flow_actions *acts);
+ const struct sw_flow_actions *, struct sw_flow_key *);
+
void ovs_dp_notify_wq(struct work_struct *work);
int action_fifos_init(void);
if (unlikely(!is_zero_ether_addr(key->ipv6.nd.sll)))
goto invalid;
ether_addr_copy(key->ipv6.nd.sll,
- &nd->opt[offset+sizeof(*nd_opt)]);
+ &nd->opt[offset+sizeof(*nd_opt)]);
} else if (nd_opt->nd_opt_type == ND_OPT_TARGET_LL_ADDR
&& opt_len == 8) {
if (unlikely(!is_zero_ether_addr(key->ipv6.nd.tll)))
goto invalid;
ether_addr_copy(key->ipv6.nd.tll,
- &nd->opt[offset+sizeof(*nd_opt)]);
+ &nd->opt[offset+sizeof(*nd_opt)]);
}
icmp_len -= opt_len;
int error;
struct ethhdr *eth;
- /* Flags are always used as part of stats. */
+ /* Flags are always used as part of stats */
key->tp.flags = 0;
skb_reset_mac_header(skb);
return 0;
}
if (nh->frag_off & htons(IP_MF) ||
- skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
+ skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
key->ip.frag = OVS_FRAG_TYPE_FIRST;
else
key->ip.frag = OVS_FRAG_TYPE_NONE;
} else {
memset(&key->tp, 0, sizeof(key->tp));
}
+
} else if (key->ip.proto == IPPROTO_UDP) {
if (udphdr_ok(skb)) {
struct udphdr *udp = udp_hdr(skb);
}
}
}
-
return 0;
}
}
int ovs_flow_key_extract(const struct ovs_tunnel_info *tun_info,
- struct sk_buff *skb,
- struct sw_flow_key *key)
+ struct sk_buff *skb, struct sw_flow_key *key)
{
/* Extract metadata from packet. */
if (tun_info) {
if (tun_info->options) {
memcpy(GENEVE_OPTS(key, tun_info->options_len),
- tun_info->options, tun_info->options_len);
+ tun_info->options, tun_info->options_len);
key->tun_opts_len = tun_info->options_len;
} else {
key->tun_opts_len = 0;
#include <linux/jiffies.h>
#include <linux/time.h>
#include <linux/flex_array.h>
-
#include <net/inet_ecn.h>
-#include <net/ip_tunnels.h>
struct sk_buff;
* maximum size. This allows us to get the benefits of variable length
* matching for small options.
*/
-#define GENEVE_OPTS(flow_key, opt_len) (struct geneve_opt *) \
- ((flow_key)->tun_opts + \
- FIELD_SIZEOF(struct sw_flow_key, tun_opts) - \
- opt_len)
+#define GENEVE_OPTS(flow_key, opt_len) \
+ ((struct geneve_opt *)((flow_key)->tun_opts + \
+ FIELD_SIZEOF(struct sw_flow_key, tun_opts) - \
+ opt_len))
static inline void __ovs_flow_tun_info_init(struct ovs_tunnel_info *tun_info,
__be32 saddr, __be32 daddr,
/* Clear struct padding. */
if (sizeof(tun_info->tunnel) != OVS_TUNNEL_KEY_SIZE)
- memset((unsigned char *) &tun_info->tunnel +
- OVS_TUNNEL_KEY_SIZE,
- 0, sizeof(tun_info->tunnel) - OVS_TUNNEL_KEY_SIZE);
+ memset((unsigned char *)&tun_info->tunnel + OVS_TUNNEL_KEY_SIZE,
+ 0, sizeof(tun_info->tunnel) - OVS_TUNNEL_KEY_SIZE);
tun_info->options = opts;
tun_info->options_len = opts_len;
} eth;
union {
struct {
- __be32 top_lse; /* top label stack entry */
+ __be32 top_lse; /* top label stack entry */
} mpls;
struct {
- u8 proto; /* IP protocol or lower 8 bits of ARP opcode. */
- u8 tos; /* IP ToS. */
- u8 ttl; /* IP TTL/hop limit. */
- u8 frag; /* One of OVS_FRAG_TYPE_*. */
+ u8 proto; /* IP protocol or lower 8 bits of ARP opcode. */
+ u8 tos; /* IP ToS. */
+ u8 ttl; /* IP TTL/hop limit. */
+ u8 frag; /* One of OVS_FRAG_TYPE_*. */
} ip;
};
struct {
void ovs_flow_stats_clear(struct sw_flow *);
u64 ovs_flow_used_time(unsigned long flow_jiffies);
+/* Update the non-metadata part of the flow key using skb. */
+int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key);
int ovs_flow_key_extract(const struct ovs_tunnel_info *tun_info,
- struct sk_buff *skb, struct sw_flow_key *key);
+ struct sk_buff *skb,
+ struct sw_flow_key *key);
/* Extract key from packet coming from userspace. */
int ovs_flow_key_extract_userspace(const struct nlattr *attr,
struct sk_buff *skb,
struct sw_flow_key *key, bool log);
-/* Update the non-metadata part of the flow key using skb. */
-int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key);
#endif /* flow.h */
mask_allowed |= 1ULL << OVS_KEY_ATTR_ARP;
}
-
if (eth_p_mpls(match->key->eth.type)) {
key_expected |= 1ULL << OVS_KEY_ATTR_MPLS;
if (match->mask && (match->mask->key.eth.type == htons(0xffff)))
if ((key_attrs & key_expected) != key_expected) {
/* Key attributes check failed. */
- OVS_NLERR(log,
- "Missing expected key attributes (key_attrs=%llx, expected=%llx).",
+ OVS_NLERR(log, "Missing key (keys=%llx, expected=%llx)",
(unsigned long long)key_attrs,
(unsigned long long)key_expected);
return false;
if ((mask_attrs & mask_allowed) != mask_attrs) {
/* Mask attributes check failed. */
- OVS_NLERR(log,
- "Contain more than allowed mask fields (mask_attrs=%llx, mask_allowed=%llx).",
+ OVS_NLERR(log, "Unexpected mask (mask=%llx, allowed=%llx)",
(unsigned long long)mask_attrs,
(unsigned long long)mask_allowed);
return false;
[OVS_KEY_ATTR_ICMPV6] = sizeof(struct ovs_key_icmpv6),
[OVS_KEY_ATTR_ARP] = sizeof(struct ovs_key_arp),
[OVS_KEY_ATTR_ND] = sizeof(struct ovs_key_nd),
- [OVS_KEY_ATTR_DP_HASH] = sizeof(u32),
[OVS_KEY_ATTR_RECIRC_ID] = sizeof(u32),
+ [OVS_KEY_ATTR_DP_HASH] = sizeof(u32),
[OVS_KEY_ATTR_TUNNEL] = -1,
[OVS_KEY_ATTR_MPLS] = sizeof(struct ovs_key_mpls),
};
int expected_len;
if (type > OVS_KEY_ATTR_MAX) {
- OVS_NLERR(log,
- "Unknown key attribute (type=%d, max=%d).",
+ OVS_NLERR(log, "Key type %d is out of range max %d",
type, OVS_KEY_ATTR_MAX);
return -EINVAL;
}
if (attrs & (1ULL << type)) {
- OVS_NLERR(log, "Duplicate key attribute (type %d).",
- type);
+ OVS_NLERR(log, "Duplicate key (type %d).", type);
return -EINVAL;
}
expected_len = ovs_key_lens[type];
if (nla_len(nla) != expected_len && expected_len != -1) {
- OVS_NLERR(log, "Key attribute has unexpected length "
- "(type=%d, length=%d, expected=%d).", type,
- nla_len(nla), expected_len);
+ OVS_NLERR(log, "Key %d has unexpected len %d expected %d",
+ type, nla_len(nla), expected_len);
return -EINVAL;
}
return __parse_flow_nlattrs(attr, a, attrsp, log, false);
}
+static int genev_tun_opt_from_nlattr(const struct nlattr *a,
+ struct sw_flow_match *match, bool is_mask,
+ bool log)
+{
+ unsigned long opt_key_offset;
+
+ if (nla_len(a) > sizeof(match->key->tun_opts)) {
+ OVS_NLERR(log, "Geneve option length err (len %d, max %zu).",
+ nla_len(a), sizeof(match->key->tun_opts));
+ return -EINVAL;
+ }
+
+ if (nla_len(a) % 4 != 0) {
+ OVS_NLERR(log, "Geneve opt len %d is not a multiple of 4.",
+ nla_len(a));
+ return -EINVAL;
+ }
+
+ /* We need to record the length of the options passed
+ * down, otherwise packets with the same format but
+ * additional options will be silently matched.
+ */
+ if (!is_mask) {
+ SW_FLOW_KEY_PUT(match, tun_opts_len, nla_len(a),
+ false);
+ } else {
+ /* This is somewhat unusual because it looks at
+ * both the key and mask while parsing the
+ * attributes (and by extension assumes the key
+ * is parsed first). Normally, we would verify
+ * that each is the correct length and that the
+ * attributes line up in the validate function.
+ * However, that is difficult because this is
+ * variable length and we won't have the
+ * information later.
+ */
+ if (match->key->tun_opts_len != nla_len(a)) {
+ OVS_NLERR(log, "Geneve option len %d != mask len %d",
+ match->key->tun_opts_len, nla_len(a));
+ return -EINVAL;
+ }
+
+ SW_FLOW_KEY_PUT(match, tun_opts_len, 0xff, true);
+ }
+
+ opt_key_offset = (unsigned long)GENEVE_OPTS((struct sw_flow_key *)0,
+ nla_len(a));
+ SW_FLOW_KEY_MEMCPY_OFFSET(match, opt_key_offset, nla_data(a),
+ nla_len(a), is_mask);
+ return 0;
+}
+
static int ipv4_tun_from_nlattr(const struct nlattr *attr,
struct sw_flow_match *match, bool is_mask,
bool log)
nla_for_each_nested(a, attr, rem) {
int type = nla_type(a);
+ int err;
+
static const u32 ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] = {
[OVS_TUNNEL_KEY_ATTR_ID] = sizeof(u64),
[OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = sizeof(u32),
};
if (type > OVS_TUNNEL_KEY_ATTR_MAX) {
- OVS_NLERR(log,
- "Unknown tunnel attribute (type=%d, max=%d).",
+ OVS_NLERR(log, "Tunnel attr %d out of range max %d",
type, OVS_TUNNEL_KEY_ATTR_MAX);
return -EINVAL;
}
if (ovs_tunnel_key_lens[type] != nla_len(a) &&
ovs_tunnel_key_lens[type] != -1) {
- OVS_NLERR(log,
- "Tunnel attribute has unexpected length "
- "(type=%d, length=%d, expected=%d).",
- type, nla_len(a),
- ovs_tunnel_key_lens[type]);
+ OVS_NLERR(log, "Tunnel attr %d has unexpected len %d expected %d",
+ type, nla_len(a), ovs_tunnel_key_lens[type]);
return -EINVAL;
}
tun_flags |= TUNNEL_OAM;
break;
case OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS:
- tun_flags |= TUNNEL_OPTIONS_PRESENT;
- if (nla_len(a) > sizeof(match->key->tun_opts)) {
- OVS_NLERR(log, "Geneve option too long "
- "(len %d, max %zu).",
- nla_len(a),
- sizeof(match->key->tun_opts));
- return -EINVAL;
- }
-
- if (nla_len(a) % 4 != 0) {
- OVS_NLERR(log, "Geneve option length is not "
- "a multiple of 4 (len %d).",
- nla_len(a));
- return -EINVAL;
- }
-
- /* We need to record the length of the options passed
- * down, otherwise packets with the same format but
- * additional options will be silently matched.
- */
- if (!is_mask) {
- SW_FLOW_KEY_PUT(match, tun_opts_len, nla_len(a),
- false);
- } else {
- /* This is somewhat unusual because it looks at
- * both the key and mask while parsing the
- * attributes (and by extension assumes the key
- * is parsed first). Normally, we would verify
- * that each is the correct length and that the
- * attributes line up in the validate function.
- * However, that is difficult because this is
- * variable length and we won't have the
- * information later.
- */
- if (match->key->tun_opts_len != nla_len(a)) {
- OVS_NLERR(log,
- "Geneve option key length (%d)"
- " is different from mask length (%d).",
- match->key->tun_opts_len,
- nla_len(a));
- return -EINVAL;
- }
-
- SW_FLOW_KEY_PUT(match, tun_opts_len, 0xff,
- true);
- }
+ err = genev_tun_opt_from_nlattr(a, match, is_mask, log);
+ if (err)
+ return err;
- SW_FLOW_KEY_MEMCPY_OFFSET(match,
- (unsigned long)GENEVE_OPTS((struct sw_flow_key *)0,
- nla_len(a)),
- nla_data(a), nla_len(a), is_mask);
+ tun_flags |= TUNNEL_OPTIONS_PRESENT;
break;
default:
- OVS_NLERR(log, "Unknown IPv4 tunnel attribute (%d).",
+ OVS_NLERR(log, "Unknown IPv4 tunnel attribute %d",
type);
return -EINVAL;
}
if (!is_mask) {
if (!match->key->tun_key.ipv4_dst) {
- OVS_NLERR(log,
- "IPv4 tunnel destination address is zero.");
+ OVS_NLERR(log, "IPv4 tunnel dst address is zero");
return -EINVAL;
}
nla_put_be64(skb, OVS_TUNNEL_KEY_ATTR_ID, output->tun_id))
return -EMSGSIZE;
if (output->ipv4_src &&
- nla_put_be32(skb, OVS_TUNNEL_KEY_ATTR_IPV4_SRC, output->ipv4_src))
+ nla_put_be32(skb, OVS_TUNNEL_KEY_ATTR_IPV4_SRC, output->ipv4_src))
return -EMSGSIZE;
if (output->ipv4_dst &&
- nla_put_be32(skb, OVS_TUNNEL_KEY_ATTR_IPV4_DST, output->ipv4_dst))
+ nla_put_be32(skb, OVS_TUNNEL_KEY_ATTR_IPV4_DST, output->ipv4_dst))
return -EMSGSIZE;
if (output->ipv4_tos &&
- nla_put_u8(skb, OVS_TUNNEL_KEY_ATTR_TOS, output->ipv4_tos))
+ nla_put_u8(skb, OVS_TUNNEL_KEY_ATTR_TOS, output->ipv4_tos))
return -EMSGSIZE;
if (nla_put_u8(skb, OVS_TUNNEL_KEY_ATTR_TTL, output->ipv4_ttl))
return -EMSGSIZE;
if ((output->tun_flags & TUNNEL_DONT_FRAGMENT) &&
- nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT))
+ nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT))
return -EMSGSIZE;
if ((output->tun_flags & TUNNEL_CSUM) &&
- nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_CSUM))
+ nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_CSUM))
return -EMSGSIZE;
if (output->tp_src &&
- nla_put_be16(skb, OVS_TUNNEL_KEY_ATTR_TP_SRC, output->tp_src))
+ nla_put_be16(skb, OVS_TUNNEL_KEY_ATTR_TP_SRC, output->tp_src))
return -EMSGSIZE;
if (output->tp_dst &&
- nla_put_be16(skb, OVS_TUNNEL_KEY_ATTR_TP_DST, output->tp_dst))
+ nla_put_be16(skb, OVS_TUNNEL_KEY_ATTR_TP_DST, output->tp_dst))
return -EMSGSIZE;
if ((output->tun_flags & TUNNEL_OAM) &&
- nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_OAM))
+ nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_OAM))
return -EMSGSIZE;
if (tun_opts &&
nla_put(skb, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS,
return 0;
}
-
static int ipv4_tun_to_nlattr(struct sk_buff *skb,
const struct ovs_key_ipv4_tunnel *output,
const struct geneve_opt *tun_opts,
if (is_mask) {
in_port = 0xffffffff; /* Always exact match in_port. */
} else if (in_port >= DP_MAX_PORTS) {
- OVS_NLERR(log,
- "Input port (%d) exceeds maximum allowable (%d).",
+ OVS_NLERR(log, "Port %d exceeds max allowable %d",
in_port, DP_MAX_PORTS);
return -EINVAL;
}
tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
if (!(tci & htons(VLAN_TAG_PRESENT))) {
if (is_mask)
- OVS_NLERR(log,
- "VLAN TCI mask does not have exact match for VLAN_TAG_PRESENT bit.");
+ OVS_NLERR(log, "VLAN TCI mask does not have exact match for VLAN_TAG_PRESENT bit.");
else
- OVS_NLERR(log,
- "VLAN TCI does not have VLAN_TAG_PRESENT bit set.");
+ OVS_NLERR(log, "VLAN TCI does not have VLAN_TAG_PRESENT bit set.");
return -EINVAL;
}
/* Always exact match EtherType. */
eth_type = htons(0xffff);
} else if (ntohs(eth_type) < ETH_P_802_3_MIN) {
- OVS_NLERR(log,
- "EtherType is less than minimum (type=%x, min=%x).",
+ OVS_NLERR(log, "EtherType %x is less than min %x",
ntohs(eth_type), ETH_P_802_3_MIN);
return -EINVAL;
}
ipv4_key = nla_data(a[OVS_KEY_ATTR_IPV4]);
if (!is_mask && ipv4_key->ipv4_frag > OVS_FRAG_TYPE_MAX) {
- OVS_NLERR(log,
- "Unknown IPv4 fragment type (value=%d, max=%d).",
+ OVS_NLERR(log, "IPv4 frag type %d is out of range max %d",
ipv4_key->ipv4_frag, OVS_FRAG_TYPE_MAX);
return -EINVAL;
}
ipv6_key = nla_data(a[OVS_KEY_ATTR_IPV6]);
if (!is_mask && ipv6_key->ipv6_frag > OVS_FRAG_TYPE_MAX) {
- OVS_NLERR(log,
- "Unknown IPv6 fragment type (value=%d, max=%d).",
+ OVS_NLERR(log, "IPv6 frag type %d is out of range max %d",
ipv6_key->ipv6_frag, OVS_FRAG_TYPE_MAX);
return -EINVAL;
}
}
if (attrs != 0) {
- OVS_NLERR(log, "Unknown key attributes (%llx).",
+ OVS_NLERR(log, "Unknown key attributes %llx",
(unsigned long long)attrs);
return -EINVAL;
}
} else if (!tci) {
/* Corner case for truncated 802.1Q header. */
if (nla_len(encap)) {
- OVS_NLERR(log,
- "Truncated 802.1Q header has non-zero encap attribute.");
+ OVS_NLERR(log, "Truncated 802.1Q header has non-zero encap attribute.");
return -EINVAL;
}
} else {
- OVS_NLERR(log,
- "Encap attribute is set for a non-VLAN frame.");
+ OVS_NLERR(log, "Encap attr is set for non-VLAN frame");
return -EINVAL;
}
}
return err;
if (match->mask) {
-
if (!nla_mask) {
/* Create an exact match mask. We need to set to 0xff
* all the 'match->mask' fields that have been touched
* 'match->mask', because padding bytes and fields not
* specified in 'match->key' should be left to 0.
* Instead, we use a stream of netlink attributes,
- * copied from 'key' and set to 0xff: ovs_key_from_nlattrs()
- * will take care of filling 'match->mask'
- * appropriately.
+ * copied from 'key' and set to 0xff.
+ * ovs_key_from_nlattrs() will take care of filling
+ * 'match->mask' appropriately.
*/
newmask = kmemdup(nla_key,
nla_total_size(nla_len(nla_key)),
__be16 tci = 0;
if (!encap_valid) {
- OVS_NLERR(log,
- "Encap mask attribute is set for non-VLAN frame.");
+ OVS_NLERR(log, "Encap mask attribute is set for non-VLAN frame.");
err = -EINVAL;
goto free_newmask;
}
if (err)
goto free_newmask;
} else {
- OVS_NLERR(log,
- "VLAN frames must have an exact match on the TPID (mask=%x).",
+ OVS_NLERR(log, "VLAN frames must have an exact match on the TPID (mask=%x).",
ntohs(eth_type));
err = -EINVAL;
goto free_newmask;
tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
if (!(tci & htons(VLAN_TAG_PRESENT))) {
- OVS_NLERR(log,
- "VLAN tag present bit must have an exact match (tci_mask=%x).",
+ OVS_NLERR(log, "VLAN tag present bit must have an exact match (tci_mask=%x).",
ntohs(tci));
err = -EINVAL;
goto free_newmask;
* get the metadata, that is, the parts of the flow key that cannot be
* extracted from the packet itself.
*/
+
int ovs_nla_get_flow_metadata(const struct nlattr *attr,
struct sw_flow_key *key,
bool log)
struct nlattr *nla, *encap;
bool is_mask = (swkey != output);
- if (nla_put_u32(skb, OVS_KEY_ATTR_DP_HASH, output->ovs_flow_hash))
+ if (nla_put_u32(skb, OVS_KEY_ATTR_RECIRC_ID, output->recirc_id))
goto nla_put_failure;
- if (nla_put_u32(skb, OVS_KEY_ATTR_RECIRC_ID, output->recirc_id))
+ if (nla_put_u32(skb, OVS_KEY_ATTR_DP_HASH, output->ovs_flow_hash))
goto nla_put_failure;
if (nla_put_u32(skb, OVS_KEY_ATTR_PRIORITY, output->phy.priority))
opts = GENEVE_OPTS(output, swkey->tun_opts_len);
if (ipv4_tun_to_nlattr(skb, &output->tun_key, opts,
- swkey->tun_opts_len))
+ swkey->tun_opts_len))
goto nla_put_failure;
}
struct sw_flow_actions *sfa;
if (size > MAX_ACTIONS_BUFSIZE) {
- OVS_NLERR(log, "Flow action size (%u bytes) exceeds maximum "
- "(%u bytes)", size, MAX_ACTIONS_BUFSIZE);
+ OVS_NLERR(log, "Flow action size %u bytes exceeds max", size);
return ERR_PTR(-EINVAL);
}
return (struct nlattr *) ((unsigned char *)(*sfa) + next_offset);
}
-static struct nlattr *__add_action(struct sw_flow_actions **sfa, int attrtype,
- void *data, int len, bool log)
+static struct nlattr *__add_action(struct sw_flow_actions **sfa,
+ int attrtype, void *data, int len, bool log)
{
struct nlattr *a;
* it to tun_info and then point there.
*/
memcpy((tun_info + 1), GENEVE_OPTS(&key, key.tun_opts_len),
- key.tun_opts_len);
+ key.tun_opts_len);
tun_info->options = (struct geneve_opt *)(tun_info + 1);
} else {
tun_info->options = NULL;
if (nla_get_u32(a) >= DP_MAX_PORTS)
return -EINVAL;
out_tnl_port = false;
+
break;
case OVS_ACTION_ATTR_HASH: {
&out_tnl_port, eth_type, log);
if (err)
return err;
+
skip_copy = out_tnl_port;
break;
break;
default:
+ OVS_NLERR(log, "Unknown Action type %d", type);
return -EINVAL;
}
if (!skip_copy) {
u32 *n_mask_hit);
struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *,
const struct sw_flow_key *);
-struct sw_flow *ovs_flow_tbl_lookup_exact(struct flow_table *,
+struct sw_flow *ovs_flow_tbl_lookup_exact(struct flow_table *tbl,
const struct sw_flow_match *match);
-
bool ovs_flow_cmp_unmasked_key(const struct sw_flow *flow,
const struct sw_flow_match *match);
OVS_VPORT_TYPE_UNSPEC,
OVS_VPORT_TYPE_NETDEV, /* network device */
OVS_VPORT_TYPE_INTERNAL, /* network device implemented by datapath */
- OVS_VPORT_TYPE_GRE, /* GRE tunnel. */
- OVS_VPORT_TYPE_VXLAN, /* VXLAN tunnel */
- OVS_VPORT_TYPE_GENEVE, /* Geneve tunnel */
+ OVS_VPORT_TYPE_GRE, /* GRE tunnel. */
+ OVS_VPORT_TYPE_VXLAN, /* VXLAN tunnel. */
+ OVS_VPORT_TYPE_GENEVE, /* Geneve tunnel. */
OVS_VPORT_TYPE_GRE64 = 104, /* GRE tunnel with 64-bit keys */
OVS_VPORT_TYPE_LISP = 105, /* LISP tunnel */
__OVS_VPORT_TYPE_MAX
OVS_KEY_ATTR_ARP, /* struct ovs_key_arp */
OVS_KEY_ATTR_ND, /* struct ovs_key_nd */
OVS_KEY_ATTR_SKB_MARK, /* u32 skb mark */
- OVS_KEY_ATTR_TUNNEL, /* Nested set of ovs_tunnel attributes */
+ OVS_KEY_ATTR_TUNNEL, /* Nested set of ovs_tunnel attributes */
OVS_KEY_ATTR_SCTP, /* struct ovs_key_sctp */
OVS_KEY_ATTR_TCP_FLAGS, /* be16 TCP flags. */
- OVS_KEY_ATTR_DP_HASH, /* u32 hash value. Value 0 indicates the hash
+ OVS_KEY_ATTR_DP_HASH, /* u32 hash value. Value 0 indicates the hash
is not computed by the datapath. */
OVS_KEY_ATTR_RECIRC_ID, /* u32 recirc id */
OVS_KEY_ATTR_MPLS, /* array of struct ovs_key_mpls.
#define OVS_KEY_ATTR_MAX (__OVS_KEY_ATTR_MAX - 1)
enum ovs_tunnel_key_attr {
- OVS_TUNNEL_KEY_ATTR_ID, /* be64 Tunnel ID */
- OVS_TUNNEL_KEY_ATTR_IPV4_SRC, /* be32 src IP address. */
- OVS_TUNNEL_KEY_ATTR_IPV4_DST, /* be32 dst IP address. */
- OVS_TUNNEL_KEY_ATTR_TOS, /* u8 Tunnel IP ToS. */
- OVS_TUNNEL_KEY_ATTR_TTL, /* u8 Tunnel IP TTL. */
- OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT, /* No argument, set DF. */
- OVS_TUNNEL_KEY_ATTR_CSUM, /* No argument. CSUM packet. */
- OVS_TUNNEL_KEY_ATTR_OAM, /* No argument, OAM frame. */
- OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS, /* Array of Geneve options */
+ OVS_TUNNEL_KEY_ATTR_ID, /* be64 Tunnel ID */
+ OVS_TUNNEL_KEY_ATTR_IPV4_SRC, /* be32 src IP address. */
+ OVS_TUNNEL_KEY_ATTR_IPV4_DST, /* be32 dst IP address. */
+ OVS_TUNNEL_KEY_ATTR_TOS, /* u8 Tunnel IP ToS. */
+ OVS_TUNNEL_KEY_ATTR_TTL, /* u8 Tunnel IP TTL. */
+ OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT, /* No argument, set DF. */
+ OVS_TUNNEL_KEY_ATTR_CSUM, /* No argument. CSUM packet. */
+ OVS_TUNNEL_KEY_ATTR_OAM, /* No argument. OAM frame. */
+ OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS, /* Array of Geneve options. */
OVS_TUNNEL_KEY_ATTR_TP_SRC, /* be16 src Transport Port. */
OVS_TUNNEL_KEY_ATTR_TP_DST, /* be16 dst Transport Port. */
__OVS_TUNNEL_KEY_ATTR_MAX
};
+
#define OVS_TUNNEL_KEY_ATTR_MAX (__OVS_TUNNEL_KEY_ATTR_MAX - 1)
/**
};
struct ovs_key_nd {
- __be32 nd_target[4];
- __u8 nd_sll[ETH_ALEN];
- __u8 nd_tll[ETH_ALEN];
+ __be32 nd_target[4];
+ __u8 nd_sll[ETH_ALEN];
+ __u8 nd_tll[ETH_ALEN];
};
/**
enum ovs_hash_alg {
OVS_HASH_ALG_L4,
};
+
/*
* struct ovs_action_hash - %OVS_ACTION_ATTR_HASH action argument.
* @hash_alg: Algorithm used to compute hash prior to recirculation.
* @hash_basis: basis used for computing hash.
*/
struct ovs_action_hash {
- uint32_t hash_alg; /* One of ovs_hash_alg. */
+ uint32_t hash_alg; /* One of ovs_hash_alg. */
uint32_t hash_basis;
};
OVS_ACTION_ATTR_PUSH_VLAN, /* struct ovs_action_push_vlan. */
OVS_ACTION_ATTR_POP_VLAN, /* No argument. */
OVS_ACTION_ATTR_SAMPLE, /* Nested OVS_SAMPLE_ATTR_*. */
- OVS_ACTION_ATTR_RECIRC, /* u32 recirc_id. */
+ OVS_ACTION_ATTR_RECIRC, /* u32 recirc_id. */
OVS_ACTION_ATTR_HASH, /* struct ovs_action_hash. */
OVS_ACTION_ATTR_PUSH_MPLS, /* struct ovs_action_push_mpls. */
OVS_ACTION_ATTR_POP_MPLS, /* __be16 ethertype. */
* data immediately followed by a mask.
* The data must be zero for the unmasked
* bits. */
+
__OVS_ACTION_ATTR_MAX
};
const struct vport_ops *ops;
struct pcpu_sw_netstats __percpu *percpu_stats;
+
struct vport_err_stats err_stats;
};
* @get_name: Get the device's name.
* @send: Send a packet on the device. Returns the length of the packet sent,
* zero for dropped packets or negative for error.
- * @get_egress_tun_info: Get the egress tunnel 5-tuple and other info for a packet.
+ * @get_egress_tun_info: Get the egress tunnel 5-tuple and other info for
+ * a packet.
*/
struct vport_ops {
enum ovs_vport_type type;
const char *(*get_name)(const struct vport *);
int (*send)(struct vport *, struct sk_buff *);
-
int (*get_egress_tun_info)(struct vport *, struct sk_buff *,
struct ovs_tunnel_info *);
};