summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/netdev-offload-tc.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c
index 474f54c52..bbdc5d14d 100644
--- a/lib/netdev-offload-tc.c
+++ b/lib/netdev-offload-tc.c
@@ -1217,6 +1217,21 @@ parse_put_flow_set_action(struct tc_flower *flower, struct tc_action *action,
return 0;
}
+static bool
+is_ipv6_fragment_and_masked(const struct flow *key, const struct flow *mask)
+{
+ if (key->dl_type != htons(ETH_P_IPV6)) {
+ return false;
+ }
+ if (mask->nw_proto && key->nw_proto == IPPROTO_FRAGMENT) {
+ return true;
+ }
+ if (key->nw_frag & (mask->nw_frag & FLOW_NW_FRAG_ANY)) {
+ return true;
+ }
+ return false;
+}
+
static int
test_key_and_mask(struct match *match)
{
@@ -1323,6 +1338,11 @@ test_key_and_mask(struct match *match)
return EOPNOTSUPP;
}
+ if (is_ipv6_fragment_and_masked(key, mask)) {
+ VLOG_DBG_RL(&rl, "offloading of IPv6 fragments isn't supported");
+ return EOPNOTSUPP;
+ }
+
if (!is_all_zeros(mask, sizeof *mask)) {
VLOG_DBG_RL(&rl, "offloading isn't supported, unknown attribute");
return EOPNOTSUPP;
@@ -1573,7 +1593,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,
mask->dl_type = 0;
mask->in_port.odp_port = 0;
- if (is_ip_any(key)) {
+ if (is_ip_any(key) && !is_ipv6_fragment_and_masked(key, mask)) {
flower.key.ip_proto = key->nw_proto;
flower.mask.ip_proto = mask->nw_proto;
mask->nw_proto = 0;