lkml.org 
[lkml]   [2022]   [Jan]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.16 0368/1039] net/xfrm: IPsec tunnel mode fix inner_ipproto setting in sec_path
    Date
    From: Raed Salem <raeds@nvidia.com>

    [ Upstream commit 45a98ef4922def8c679ca7c454403d1957fe70e7 ]

    The inner_ipproto saves the inner IP protocol of the plain
    text packet. This allows vendor's IPsec feature making offload
    decision at skb's features_check and configuring hardware at
    ndo_start_xmit, current code implenetation did not handle the
    case where IPsec is used in tunnel mode.

    Fix by handling the case when IPsec is used in tunnel mode by
    reading the protocol of the plain text packet IP protocol.

    Fixes: fa4535238fb5 ("net/xfrm: Add inner_ipproto into sec_path")
    Signed-off-by: Raed Salem <raeds@nvidia.com>
    Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    net/xfrm/xfrm_output.c | 30 +++++++++++++++++++++++++-----
    1 file changed, 25 insertions(+), 5 deletions(-)

    diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
    index 229544bc70c21..4dc4a7bbe51cf 100644
    --- a/net/xfrm/xfrm_output.c
    +++ b/net/xfrm/xfrm_output.c
    @@ -647,10 +647,12 @@ static int xfrm_output_gso(struct net *net, struct sock *sk, struct sk_buff *skb
    * This requires hardware to know the inner packet type to calculate
    * the inner header checksum. Save inner ip protocol here to avoid
    * traversing the packet in the vendor's xmit code.
    - * If the encap type is IPIP, just save skb->inner_ipproto. Otherwise,
    - * get the ip protocol from the IP header.
    + * For IPsec tunnel mode save the ip protocol from the IP header of the
    + * plain text packet. Otherwise If the encap type is IPIP, just save
    + * skb->inner_ipproto in any other case get the ip protocol from the IP
    + * header.
    */
    -static void xfrm_get_inner_ipproto(struct sk_buff *skb)
    +static void xfrm_get_inner_ipproto(struct sk_buff *skb, struct xfrm_state *x)
    {
    struct xfrm_offload *xo = xfrm_offload(skb);
    const struct ethhdr *eth;
    @@ -658,6 +660,25 @@ static void xfrm_get_inner_ipproto(struct sk_buff *skb)
    if (!xo)
    return;

    + if (x->outer_mode.encap == XFRM_MODE_TUNNEL) {
    + switch (x->outer_mode.family) {
    + case AF_INET:
    + xo->inner_ipproto = ip_hdr(skb)->protocol;
    + break;
    + case AF_INET6:
    + xo->inner_ipproto = ipv6_hdr(skb)->nexthdr;
    + break;
    + default:
    + break;
    + }
    +
    + return;
    + }
    +
    + /* non-Tunnel Mode */
    + if (!skb->encapsulation)
    + return;
    +
    if (skb->inner_protocol_type == ENCAP_TYPE_IPPROTO) {
    xo->inner_ipproto = skb->inner_ipproto;
    return;
    @@ -712,8 +733,7 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb)
    sp->xvec[sp->len++] = x;
    xfrm_state_hold(x);

    - if (skb->encapsulation)
    - xfrm_get_inner_ipproto(skb);
    + xfrm_get_inner_ipproto(skb, x);
    skb->encapsulation = 1;

    if (skb_is_gso(skb)) {
    --
    2.34.1


    \
     
     \ /
      Last update: 2022-01-25 01:11    [W:4.027 / U:0.344 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site