Skip to content

Commit

Permalink
ipv6: sr: add support for encapsulation of L2 frames
Browse files Browse the repository at this point in the history
This patch implements the L2 frame encapsulation mechanism, referred to
as T.Encaps.L2 in the SRv6 specifications [1].

A new type of SRv6 tunnel mode is added (SEG6_IPTUN_MODE_L2ENCAP). It only
accepts packets with an existing MAC header (i.e., it will not work for
locally generated packets). The resulting packet looks like IPv6 -> SRH ->
Ethernet -> original L3 payload. The next header field of the SRH is set to
NEXTHDR_NONE.

[1] https://tools.ietf.org/html/draft-filsfils-spring-srv6-network-programming-01

Signed-off-by: David Lebrun <david.lebrun@uclouvain.be>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David Lebrun authored and David S. Miller committed Aug 26, 2017
1 parent 32d99d0 commit 38ee7f2
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 6 deletions.
18 changes: 14 additions & 4 deletions include/uapi/linux/seg6_iptunnel.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,26 @@ struct seg6_iptunnel_encap {
enum {
SEG6_IPTUN_MODE_INLINE,
SEG6_IPTUN_MODE_ENCAP,
SEG6_IPTUN_MODE_L2ENCAP,
};

#ifdef __KERNEL__

static inline size_t seg6_lwt_headroom(struct seg6_iptunnel_encap *tuninfo)
{
int encap = (tuninfo->mode == SEG6_IPTUN_MODE_ENCAP);

return ((tuninfo->srh->hdrlen + 1) << 3) +
(encap * sizeof(struct ipv6hdr));
int head = 0;

switch (tuninfo->mode) {
case SEG6_IPTUN_MODE_INLINE:
break;
case SEG6_IPTUN_MODE_ENCAP:
head = sizeof(struct ipv6hdr);
break;
case SEG6_IPTUN_MODE_L2ENCAP:
return 0;
}

return ((tuninfo->srh->hdrlen + 1) << 3) + head;
}

#endif
Expand Down
25 changes: 23 additions & 2 deletions net/ipv6/seg6_iptunnel.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,22 @@ static int seg6_do_srh(struct sk_buff *skb)
if (err)
return err;

skb->protocol = htons(ETH_P_IPV6);
break;
case SEG6_IPTUN_MODE_L2ENCAP:
if (!skb_mac_header_was_set(skb))
return -EINVAL;

if (pskb_expand_head(skb, skb->mac_len, 0, GFP_ATOMIC) < 0)
return -ENOMEM;

skb_mac_header_rebuild(skb);
skb_push(skb, skb->mac_len);

err = seg6_do_srh_encap(skb, tinfo->srh, NEXTHDR_NONE);
if (err)
return err;

skb->protocol = htons(ETH_P_IPV6);
break;
}
Expand Down Expand Up @@ -386,6 +402,8 @@ static int seg6_build_state(struct nlattr *nla,
break;
case SEG6_IPTUN_MODE_ENCAP:
break;
case SEG6_IPTUN_MODE_L2ENCAP:
break;
default:
return -EINVAL;
}
Expand All @@ -409,8 +427,11 @@ static int seg6_build_state(struct nlattr *nla,
memcpy(&slwt->tuninfo, tuninfo, tuninfo_len);

newts->type = LWTUNNEL_ENCAP_SEG6;
newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT |
LWTUNNEL_STATE_INPUT_REDIRECT;
newts->flags |= LWTUNNEL_STATE_INPUT_REDIRECT;

if (tuninfo->mode != SEG6_IPTUN_MODE_L2ENCAP)
newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT;

newts->headroom = seg6_lwt_headroom(tuninfo);

*ts = newts;
Expand Down

0 comments on commit 38ee7f2

Please sign in to comment.