X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=datapath%2Ftunnel.c;h=67556d706343579ab0cf12c43c18c6ec91466cbc;hb=45c8d3a189843f0f45398caa420b952d5acd1f19;hp=32632233659ee7cca37cb49194987fe2dd866c17;hpb=76abe283baa043bae84163873b0c7c498bfb260a;p=openvswitch diff --git a/datapath/tunnel.c b/datapath/tunnel.c index 32632233..67556d70 100644 --- a/datapath/tunnel.c +++ b/datapath/tunnel.c @@ -249,11 +249,13 @@ static int add_port(struct vport *vport) struct tbl *new_table; new_table = tbl_expand(cur_table); - if (IS_ERR(new_table)) - return PTR_ERR(new_table); - - rcu_assign_pointer(port_table, new_table); - tbl_deferred_destroy(cur_table, NULL); + if (IS_ERR(new_table)) { + if (PTR_ERR(new_table) != -ENOSPC) + return PTR_ERR(new_table); + } else { + rcu_assign_pointer(port_table, new_table); + tbl_deferred_destroy(cur_table, NULL); + } } err = tbl_insert(rtnl_dereference(port_table), &tnl_vport->tbl_node, @@ -450,9 +452,13 @@ void tnl_rcv(struct vport *vport, struct sk_buff *skb, u8 tos) secpath_reset(skb); ecn_decapsulate(skb, tos); - compute_ip_summed(skb, false); vlan_set_tci(skb, 0); + if (unlikely(compute_ip_summed(skb, false))) { + kfree_skb(skb); + return; + } + vport_receive(vport, skb); } @@ -718,7 +724,11 @@ bool tnl_frag_needed(struct vport *vport, const struct tnl_mutable_config *mutab (TNL_F_IN_KEY_MATCH | TNL_F_OUT_KEY_ACTION)) OVS_CB(nskb)->tun_id = flow_key; - compute_ip_summed(nskb, false); + if (unlikely(compute_ip_summed(nskb, false))) { + kfree_skb(nskb); + return false; + } + vport_receive(vport, nskb); return true; @@ -960,7 +970,7 @@ static struct tnl_cache *build_cache(struct vport *vport, err = flow_extract(skb, dst_vport->port_no, &flow_key, &flow_key_len, &is_frag); - kfree_skb(skb); + consume_skb(skb); if (err || is_frag) goto done; @@ -1027,27 +1037,6 @@ static struct rtable *find_route(struct vport *vport, } } -static struct sk_buff *check_headroom(struct sk_buff *skb, int headroom) -{ - if (skb_headroom(skb) < headroom || skb_header_cloned(skb)) { - struct sk_buff *nskb = skb_realloc_headroom(skb, headroom + 16); - if (unlikely(!nskb)) { - kfree_skb(skb); - return ERR_PTR(-ENOMEM); - } - - set_skb_csum_bits(skb, nskb); - - if (skb->sk) - skb_set_owner_w(nskb, skb->sk); - - kfree_skb(skb); - return nskb; - } - - return skb; -} - static inline bool need_linearize(const struct sk_buff *skb) { int i; @@ -1074,34 +1063,35 @@ static struct sk_buff *handle_offloads(struct sk_buff *skb, int min_headroom; int err; - forward_ip_summed(skb); - - err = vswitch_skb_checksum_setup(skb); - if (unlikely(err)) - goto error_free; - min_headroom = LL_RESERVED_SPACE(rt_dst(rt).dev) + rt_dst(rt).header_len + mutable->tunnel_hlen + (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0); - skb = check_headroom(skb, min_headroom); - if (IS_ERR(skb)) { - err = PTR_ERR(skb); - goto error; + if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) { + int head_delta = SKB_DATA_ALIGN(min_headroom - + skb_headroom(skb) + + 16); + err = pskb_expand_head(skb, max_t(int, head_delta, 0), + 0, GFP_ATOMIC); + if (unlikely(err)) + goto error_free; } + forward_ip_summed(skb, true); + if (skb_is_gso(skb)) { struct sk_buff *nskb; nskb = skb_gso_segment(skb, 0); - kfree_skb(skb); if (IS_ERR(nskb)) { + kfree_skb(skb); err = PTR_ERR(nskb); goto error; } + consume_skb(skb); skb = nskb; - } else if (skb->ip_summed == CHECKSUM_PARTIAL) { + } else if (get_ip_summed(skb) == OVS_CSUM_PARTIAL) { /* Pages aren't locked and could change at any time. * If this happens after we compute the checksum, the * checksum will be wrong. We linearize now to avoid @@ -1116,8 +1106,9 @@ static struct sk_buff *handle_offloads(struct sk_buff *skb, err = skb_checksum_help(skb); if (unlikely(err)) goto error_free; - } else if (skb->ip_summed == CHECKSUM_COMPLETE) - skb->ip_summed = CHECKSUM_NONE; + } + + set_ip_summed(skb, OVS_CSUM_NONE); return skb; @@ -1312,8 +1303,12 @@ int tnl_send(struct vport *vport, struct sk_buff *skb) ip_send_check(iph); if (cache_vport) { + if (unlikely(compute_ip_summed(skb, true))) { + kfree_skb(skb); + goto next; + } + OVS_CB(skb)->flow = cache->flow; - compute_ip_summed(skb, true); vport_receive(cache_vport, skb); sent_len += orig_len; } else { @@ -1346,64 +1341,64 @@ out: return sent_len; } -static const struct nla_policy tnl_policy[ODP_TUNNEL_ATTR_MAX + 1] = { - [ODP_TUNNEL_ATTR_FLAGS] = { .type = NLA_U32 }, - [ODP_TUNNEL_ATTR_DST_IPV4] = { .type = NLA_U32 }, - [ODP_TUNNEL_ATTR_SRC_IPV4] = { .type = NLA_U32 }, - [ODP_TUNNEL_ATTR_OUT_KEY] = { .type = NLA_U64 }, - [ODP_TUNNEL_ATTR_IN_KEY] = { .type = NLA_U64 }, - [ODP_TUNNEL_ATTR_TOS] = { .type = NLA_U8 }, - [ODP_TUNNEL_ATTR_TTL] = { .type = NLA_U8 }, +static const struct nla_policy tnl_policy[OVS_TUNNEL_ATTR_MAX + 1] = { + [OVS_TUNNEL_ATTR_FLAGS] = { .type = NLA_U32 }, + [OVS_TUNNEL_ATTR_DST_IPV4] = { .type = NLA_U32 }, + [OVS_TUNNEL_ATTR_SRC_IPV4] = { .type = NLA_U32 }, + [OVS_TUNNEL_ATTR_OUT_KEY] = { .type = NLA_U64 }, + [OVS_TUNNEL_ATTR_IN_KEY] = { .type = NLA_U64 }, + [OVS_TUNNEL_ATTR_TOS] = { .type = NLA_U8 }, + [OVS_TUNNEL_ATTR_TTL] = { .type = NLA_U8 }, }; -/* Sets ODP_TUNNEL_ATTR_* fields in 'mutable', which must initially be zeroed. */ +/* Sets OVS_TUNNEL_ATTR_* fields in 'mutable', which must initially be zeroed. */ static int tnl_set_config(struct nlattr *options, const struct tnl_ops *tnl_ops, const struct vport *cur_vport, struct tnl_mutable_config *mutable) { const struct vport *old_vport; const struct tnl_mutable_config *old_mutable; - struct nlattr *a[ODP_TUNNEL_ATTR_MAX + 1]; + struct nlattr *a[OVS_TUNNEL_ATTR_MAX + 1]; int err; if (!options) return -EINVAL; - err = nla_parse_nested(a, ODP_TUNNEL_ATTR_MAX, options, tnl_policy); + err = nla_parse_nested(a, OVS_TUNNEL_ATTR_MAX, options, tnl_policy); if (err) return err; - if (!a[ODP_TUNNEL_ATTR_FLAGS] || !a[ODP_TUNNEL_ATTR_DST_IPV4]) + if (!a[OVS_TUNNEL_ATTR_FLAGS] || !a[OVS_TUNNEL_ATTR_DST_IPV4]) return -EINVAL; - mutable->flags = nla_get_u32(a[ODP_TUNNEL_ATTR_FLAGS]) & TNL_F_PUBLIC; + mutable->flags = nla_get_u32(a[OVS_TUNNEL_ATTR_FLAGS]) & TNL_F_PUBLIC; - if (a[ODP_TUNNEL_ATTR_SRC_IPV4]) - mutable->saddr = nla_get_be32(a[ODP_TUNNEL_ATTR_SRC_IPV4]); - mutable->daddr = nla_get_be32(a[ODP_TUNNEL_ATTR_DST_IPV4]); + if (a[OVS_TUNNEL_ATTR_SRC_IPV4]) + mutable->saddr = nla_get_be32(a[OVS_TUNNEL_ATTR_SRC_IPV4]); + mutable->daddr = nla_get_be32(a[OVS_TUNNEL_ATTR_DST_IPV4]); - if (a[ODP_TUNNEL_ATTR_TOS]) { - mutable->tos = nla_get_u8(a[ODP_TUNNEL_ATTR_TOS]); + if (a[OVS_TUNNEL_ATTR_TOS]) { + mutable->tos = nla_get_u8(a[OVS_TUNNEL_ATTR_TOS]); if (mutable->tos != RT_TOS(mutable->tos)) return -EINVAL; } - if (a[ODP_TUNNEL_ATTR_TTL]) - mutable->ttl = nla_get_u8(a[ODP_TUNNEL_ATTR_TTL]); + if (a[OVS_TUNNEL_ATTR_TTL]) + mutable->ttl = nla_get_u8(a[OVS_TUNNEL_ATTR_TTL]); mutable->tunnel_type = tnl_ops->tunnel_type; - if (!a[ODP_TUNNEL_ATTR_IN_KEY]) { + if (!a[OVS_TUNNEL_ATTR_IN_KEY]) { mutable->tunnel_type |= TNL_T_KEY_MATCH; mutable->flags |= TNL_F_IN_KEY_MATCH; } else { mutable->tunnel_type |= TNL_T_KEY_EXACT; - mutable->in_key = nla_get_be64(a[ODP_TUNNEL_ATTR_IN_KEY]); + mutable->in_key = nla_get_be64(a[OVS_TUNNEL_ATTR_IN_KEY]); } - if (!a[ODP_TUNNEL_ATTR_OUT_KEY]) + if (!a[OVS_TUNNEL_ATTR_OUT_KEY]) mutable->flags |= TNL_F_OUT_KEY_ACTION; else - mutable->out_key = nla_get_be64(a[ODP_TUNNEL_ATTR_OUT_KEY]); + mutable->out_key = nla_get_be64(a[OVS_TUNNEL_ATTR_OUT_KEY]); mutable->tunnel_hlen = tnl_ops->hdr_len(mutable); if (mutable->tunnel_hlen < 0) @@ -1520,19 +1515,19 @@ int tnl_get_options(const struct vport *vport, struct sk_buff *skb) const struct tnl_vport *tnl_vport = tnl_vport_priv(vport); const struct tnl_mutable_config *mutable = rcu_dereference_rtnl(tnl_vport->mutable); - NLA_PUT_U32(skb, ODP_TUNNEL_ATTR_FLAGS, mutable->flags & TNL_F_PUBLIC); - NLA_PUT_BE32(skb, ODP_TUNNEL_ATTR_DST_IPV4, mutable->daddr); + NLA_PUT_U32(skb, OVS_TUNNEL_ATTR_FLAGS, mutable->flags & TNL_F_PUBLIC); + NLA_PUT_BE32(skb, OVS_TUNNEL_ATTR_DST_IPV4, mutable->daddr); if (!(mutable->flags & TNL_F_IN_KEY_MATCH)) - NLA_PUT_BE64(skb, ODP_TUNNEL_ATTR_IN_KEY, mutable->in_key); + NLA_PUT_BE64(skb, OVS_TUNNEL_ATTR_IN_KEY, mutable->in_key); if (!(mutable->flags & TNL_F_OUT_KEY_ACTION)) - NLA_PUT_BE64(skb, ODP_TUNNEL_ATTR_OUT_KEY, mutable->out_key); + NLA_PUT_BE64(skb, OVS_TUNNEL_ATTR_OUT_KEY, mutable->out_key); if (mutable->saddr) - NLA_PUT_BE32(skb, ODP_TUNNEL_ATTR_SRC_IPV4, mutable->saddr); + NLA_PUT_BE32(skb, OVS_TUNNEL_ATTR_SRC_IPV4, mutable->saddr); if (mutable->tos) - NLA_PUT_U8(skb, ODP_TUNNEL_ATTR_TOS, mutable->tos); + NLA_PUT_U8(skb, OVS_TUNNEL_ATTR_TOS, mutable->tos); if (mutable->ttl) - NLA_PUT_U8(skb, ODP_TUNNEL_ATTR_TTL, mutable->ttl); + NLA_PUT_U8(skb, OVS_TUNNEL_ATTR_TTL, mutable->ttl); return 0;