diff options
-rw-r--r-- | lib/netdev-offload-tc.c | 22 |
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; |