Skip to content

Commit

Permalink
iptfs: xfrm: generic iptfs support -- replace
Browse files Browse the repository at this point in the history
  • Loading branch information
choppsv1 committed Jul 29, 2023
1 parent 65bd5c9 commit 386beb5
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 6 deletions.
5 changes: 5 additions & 0 deletions net/ipv4/esp4_offload.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,11 @@ static struct sk_buff *xfrm4_outer_mode_gso_segment(struct xfrm_state *x,
return xfrm4_transport_gso_segment(x, skb, features);
case XFRM_MODE_BEET:
return xfrm4_beet_gso_segment(x, skb, features);
#if 0
case XFRM_MODE_IPTFS:
/* XXX chopps: writeme */
return xfrm4_iptfs_gso_segment(x, skb, features);
#endif
}

return ERR_PTR(-EOPNOTSUPP);
Expand Down
5 changes: 5 additions & 0 deletions net/ipv6/esp6_offload.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,11 @@ static struct sk_buff *xfrm6_outer_mode_gso_segment(struct xfrm_state *x,
return xfrm6_transport_gso_segment(x, skb, features);
case XFRM_MODE_BEET:
return xfrm6_beet_gso_segment(x, skb, features);
#if 0
case XFRM_MODE_IPTFS:
/* XXX chopps: writeme */
return xfrm6_iptfs_gso_segment(x, skb, features);
#endif
}

return ERR_PTR(-EOPNOTSUPP);
Expand Down
60 changes: 54 additions & 6 deletions net/xfrm/xfrm_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,8 @@ static int xfrm4_beet_encap_add(struct xfrm_state *x, struct sk_buff *skb)
*
* The top IP header will be constructed per RFC 2401.
*/
static int xfrm4_tunnel_encap_add(struct xfrm_state *x, struct sk_buff *skb)
static int __xfrm4_tunnel_encap_add(struct xfrm_state *x, struct sk_buff *skb,
u8 ipproto, u8 hdradj)
{
bool small_ipv6 = (skb->protocol == htons(ETH_P_IPV6)) && (skb->len <= IPV6_MIN_MTU);
struct dst_entry *dst = skb_dst(skb);
Expand All @@ -279,7 +280,8 @@ static int xfrm4_tunnel_encap_add(struct xfrm_state *x, struct sk_buff *skb)
skb_set_inner_network_header(skb, skb_network_offset(skb));
skb_set_inner_transport_header(skb, skb_transport_offset(skb));

skb_set_network_header(skb, -x->props.header_len);
/* backup to add space for the outer encap */
skb_set_network_header(skb, -(x->props.header_len - hdradj));
skb->mac_header = skb->network_header +
offsetof(struct iphdr, protocol);
skb->transport_header = skb->network_header + sizeof(*top_iph);
Expand All @@ -288,7 +290,7 @@ static int xfrm4_tunnel_encap_add(struct xfrm_state *x, struct sk_buff *skb)
top_iph->ihl = 5;
top_iph->version = 4;

top_iph->protocol = xfrm_af2proto(skb_dst(skb)->ops->family);
top_iph->protocol = ipproto;

/* DS disclosing depends on XFRM_SA_XFLAG_DONT_ENCAP_DSCP */
if (x->props.extra_flags & XFRM_SA_XFLAG_DONT_ENCAP_DSCP)
Expand All @@ -314,8 +316,15 @@ static int xfrm4_tunnel_encap_add(struct xfrm_state *x, struct sk_buff *skb)
return 0;
}

static int xfrm4_tunnel_encap_add(struct xfrm_state *x, struct sk_buff *skb)
{
u8 ipproto = xfrm_af2proto(skb_dst(skb)->ops->family);
return __xfrm4_tunnel_encap_add(x, skb, ipproto, 0);
}

#if IS_ENABLED(CONFIG_IPV6)
static int xfrm6_tunnel_encap_add(struct xfrm_state *x, struct sk_buff *skb)
static int __xfrm6_tunnel_encap_add(struct xfrm_state *x, struct sk_buff *skb,
u8 nexthdr, u8 hdradj)
{
struct dst_entry *dst = skb_dst(skb);
struct ipv6hdr *top_iph;
Expand All @@ -324,7 +333,7 @@ static int xfrm6_tunnel_encap_add(struct xfrm_state *x, struct sk_buff *skb)
skb_set_inner_network_header(skb, skb_network_offset(skb));
skb_set_inner_transport_header(skb, skb_transport_offset(skb));

skb_set_network_header(skb, -x->props.header_len);
skb_set_network_header(skb, -(x->props.header_len - hdradj));
skb->mac_header = skb->network_header +
offsetof(struct ipv6hdr, nexthdr);
skb->transport_header = skb->network_header + sizeof(*top_iph);
Expand All @@ -334,7 +343,7 @@ static int xfrm6_tunnel_encap_add(struct xfrm_state *x, struct sk_buff *skb)

memcpy(top_iph->flow_lbl, XFRM_MODE_SKB_CB(skb)->flow_lbl,
sizeof(top_iph->flow_lbl));
top_iph->nexthdr = xfrm_af2proto(skb_dst(skb)->ops->family);
top_iph->nexthdr = nexthdr;

if (x->props.extra_flags & XFRM_SA_XFLAG_DONT_ENCAP_DSCP)
dsfield = 0;
Expand All @@ -350,6 +359,12 @@ static int xfrm6_tunnel_encap_add(struct xfrm_state *x, struct sk_buff *skb)
return 0;
}

static int xfrm6_tunnel_encap_add(struct xfrm_state *x, struct sk_buff *skb)
{
u8 nexthdr = xfrm_af2proto(skb_dst(skb)->ops->family);
return __xfrm6_tunnel_encap_add(x, skb, nexthdr, 0);
}

static int xfrm6_beet_encap_add(struct xfrm_state *x, struct sk_buff *skb)
{
struct ipv6hdr *top_iph;
Expand Down Expand Up @@ -449,6 +464,37 @@ static int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
return -EAFNOSUPPORT;
}

static int xfrm_prepare_iptfs_output(struct xfrm_state *x, struct sk_buff *skb)
{
/* XXX what we really want to do is this:
*
* Add an extra_hdr_len to props along with header_len and trailer_len
* use this in the places that verify there's enough room saved in the
* skb_buff for the entire encap. Do *not* use this here in the
* encap_add functions, this way we do not have to subtract it back out
* like we are doing here.. So do a search on `header_len` and figure
* out which ones need to have extra_header_len added to them (all
* except here??)
*/
#if IS_ENABLED(CONFIG_XFRM_IPTFS)
/* XXX actually get this from the sub-type CC or non-CC mode */
size_t hsz = sizeof(struct ip_iptfs_hdr);

if (x->outer_mode.family == AF_INET)
return __xfrm4_tunnel_encap_add(x, skb, XFRM_PROTO_IPTFS, hsz);
else if (x->outer_mode.family == AF_INET6) {
#if IS_ENABLED(CONFIG_IPV6)
return __xfrm6_tunnel_encap_add(x, skb, XFRM_PROTO_IPTFS, hsz);
#else
WARN_ON_ONCE(1);
return -EAFNOSUPPORT;
#endif
}
#endif
WARN_ON_ONCE(1);
return -EOPNOTSUPP;
}

static int xfrm_outer_mode_output(struct xfrm_state *x, struct sk_buff *skb)
{
switch (x->props.mode) {
Expand All @@ -459,6 +505,8 @@ static int xfrm_outer_mode_output(struct xfrm_state *x, struct sk_buff *skb)
if (x->props.family == AF_INET6)
return xfrm6_prepare_output(x, skb);
break;
case XFRM_MODE_IPTFS:
return xfrm_prepare_iptfs_output(x, skb);
case XFRM_MODE_TRANSPORT:
if (x->props.family == AF_INET)
return xfrm4_transport_output(x, skb);
Expand Down

0 comments on commit 386beb5

Please sign in to comment.