#include "shash.h"
#include "sset.h"
#include "timeval.h"
-#include "tnl-arp-cache.h"
+#include "tnl-neigh-cache.h"
#include "tnl-ports.h"
#include "unixctl.h"
#include "util.h"
uint32_t mask_key_len, const struct flow *flow,
struct flow_wildcards *wc)
{
- if (mask_key_len) {
- enum odp_key_fitness fitness;
-
- fitness = odp_flow_key_to_mask_udpif(mask_key, mask_key_len, key,
- key_len, &wc->masks, flow);
- if (fitness) {
- /* This should not happen: it indicates that
- * odp_flow_key_from_mask() and odp_flow_key_to_mask()
- * disagree on the acceptable form of a mask. Log the problem
- * as an error, with enough details to enable debugging. */
- static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
-
- if (!VLOG_DROP_ERR(&rl)) {
- struct ds s;
-
- ds_init(&s);
- odp_flow_format(key, key_len, mask_key, mask_key_len, NULL, &s,
- true);
- VLOG_ERR("internal error parsing flow mask %s (%s)",
- ds_cstr(&s), odp_key_fitness_to_string(fitness));
- ds_destroy(&s);
- }
+ enum odp_key_fitness fitness;
+
+ fitness = odp_flow_key_to_mask_udpif(mask_key, mask_key_len, key,
+ key_len, wc, flow);
+ if (fitness) {
+ /* This should not happen: it indicates that
+ * odp_flow_key_from_mask() and odp_flow_key_to_mask()
+ * disagree on the acceptable form of a mask. Log the problem
+ * as an error, with enough details to enable debugging. */
+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
+
+ if (!VLOG_DROP_ERR(&rl)) {
+ struct ds s;
- return EINVAL;
+ ds_init(&s);
+ odp_flow_format(key, key_len, mask_key, mask_key_len, NULL, &s,
+ true);
+ VLOG_ERR("internal error parsing flow mask %s (%s)",
+ ds_cstr(&s), odp_key_fitness_to_string(fitness));
+ ds_destroy(&s);
}
- } else {
- flow_wildcards_init_for_packet(wc, flow);
+
+ return EINVAL;
}
return 0;
return EINVAL;
}
+ /* Userspace datapath doesn't support conntrack. */
+ if (flow->ct_state || flow->ct_zone || flow->ct_mark
+ || !ovs_u128_is_zero(&flow->ct_label)) {
+ return EINVAL;
+ }
+
return 0;
}
struct match match;
struct ds ds = DS_EMPTY_INITIALIZER;
+ match.tun_md.valid = false;
match.flow = flow->flow;
miniflow_expand(&flow->cr.mask->mf, &match.wc.masks);
ovs_mutex_unlock(&dp->non_pmd_mutex);
dp_netdev_pmd_unref(non_pmd);
- tnl_arp_cache_run();
+ tnl_neigh_cache_run();
tnl_port_map_run();
new_tnl_seq = seq_read(tnl_conf_seq);
/* Translate tunnel metadata masks to datapath format. */
if (wc) {
if (wc->masks.tunnel.metadata.present.map) {
- struct geneve_opt opts[GENEVE_TOT_OPT_SIZE /
+ struct geneve_opt opts[TLV_TOT_OPT_SIZE /
sizeof(struct geneve_opt)];
tun_metadata_to_geneve_udpif_mask(&flow->tunnel,
{
uint32_t hash, recirc_depth;
- hash = dp_packet_get_rss_hash(packet);
- if (OVS_UNLIKELY(!hash)) {
+ if (OVS_LIKELY(dp_packet_rss_valid(packet))) {
+ hash = dp_packet_get_rss_hash(packet);
+ } else {
hash = miniflow_hash_5tuple(mf, 0);
dp_packet_set_rss_hash(packet, hash);
}
miss_cnt++;
+ match.tun_md.valid = false;
miniflow_expand(&keys[i].mf, &match.flow);
ofpbuf_clear(&actions);
continue;
}
+ /* The Netlink encoding of datapath flow keys cannot express
+ * wildcarding the presence of a VLAN tag. Instead, a missing VLAN
+ * tag is interpreted as exact match on the fact that there is no
+ * VLAN. Unless we refactor a lot of code that translates between
+ * Netlink and struct flow representations, we have to do the same
+ * here. */
+ if (!match.wc.masks.vlan_tci) {
+ match.wc.masks.vlan_tci = htons(0xffff);
+ }
+
/* We can't allow the packet batching in the next loop to execute
* the actions. Otherwise, if there are any slow path actions,
* we'll send the packet up twice. */
VLOG_WARN("Packet dropped. Max recirculation depth exceeded.");
break;
+ case OVS_ACTION_ATTR_CT:
+ /* If a flow with this action is slow-pathed, datapath assistance is
+ * required to implement it. However, we don't support this action
+ * in the userspace datapath. */
+ VLOG_WARN("Cannot execute conntrack action in userspace.");
+ break;
+
case OVS_ACTION_ATTR_PUSH_VLAN:
case OVS_ACTION_ATTR_POP_VLAN:
case OVS_ACTION_ATTR_PUSH_MPLS:
static void
dpif_dummy_override(const char *type)
{
- if (!dp_unregister_provider(type)) {
+ int error;
+
+ /*
+ * Ignore EAFNOSUPPORT to allow --enable-dummy=system with
+ * a userland-only build. It's useful for testsuite.
+ */
+ error = dp_unregister_provider(type);
+ if (error == 0 || error == EAFNOSUPPORT) {
dpif_dummy_register__(type);
}
}