]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blame - include/net/erspan.h
Merge branch 'nfp-ethtool-flash-updates'
[mirror_ubuntu-eoan-kernel.git] / include / net / erspan.h
CommitLineData
84e54fe0
WT
1#ifndef __LINUX_ERSPAN_H
2#define __LINUX_ERSPAN_H
3
4/*
5 * GRE header for ERSPAN encapsulation (8 octets [34:41]) -- 8 bytes
6 * 0 1 2 3
7 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
8 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
9 * |0|0|0|1|0|00000|000000000|00000| Protocol Type for ERSPAN |
10 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
11 * | Sequence Number (increments per packet per session) |
12 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
13 *
14 * Note that in the above GRE header [RFC1701] out of the C, R, K, S,
15 * s, Recur, Flags, Version fields only S (bit 03) is set to 1. The
16 * other fields are set to zero, so only a sequence number follows.
17 *
18 * ERSPAN Type II header (8 octets [42:49])
19 * 0 1 2 3
20 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
21 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
22 * | Ver | VLAN | COS | En|T| Session ID |
23 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
24 * | Reserved | Index |
25 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
26 *
27 * GRE proto ERSPAN type II = 0x88BE, type III = 0x22EB
28 */
29
30#define ERSPAN_VERSION 0x1
31
32#define VER_MASK 0xf000
33#define VLAN_MASK 0x0fff
34#define COS_MASK 0xe000
35#define EN_MASK 0x1800
36#define T_MASK 0x0400
37#define ID_MASK 0x03ff
38#define INDEX_MASK 0xfffff
39
40enum erspan_encap_type {
41 ERSPAN_ENCAP_NOVLAN = 0x0, /* originally without VLAN tag */
42 ERSPAN_ENCAP_ISL = 0x1, /* originally ISL encapsulated */
43 ERSPAN_ENCAP_8021Q = 0x2, /* originally 802.1Q encapsulated */
44 ERSPAN_ENCAP_INFRAME = 0x3, /* VLAN tag perserved in frame */
45};
46
47struct erspan_metadata {
48 __be32 index; /* type II */
49};
50
51struct erspanhdr {
52 __be16 ver_vlan;
53#define VER_OFFSET 12
54 __be16 session_id;
55#define COS_OFFSET 13
56#define EN_OFFSET 11
57#define T_OFFSET 10
58 struct erspan_metadata md;
59};
60
a3222dc9
WT
61static inline u8 tos_to_cos(u8 tos)
62{
63 u8 dscp, cos;
64
65 dscp = tos >> 2;
66 cos = dscp >> 3;
67 return cos;
68}
69
70static inline void erspan_build_header(struct sk_buff *skb,
71 __be32 id, u32 index,
72 bool truncate, bool is_ipv4)
73{
74 struct ethhdr *eth = eth_hdr(skb);
75 enum erspan_encap_type enc_type;
76 struct erspanhdr *ershdr;
77 struct qtag_prefix {
78 __be16 eth_type;
79 __be16 tci;
80 } *qp;
81 u16 vlan_tci = 0;
82 u8 tos;
83
84 tos = is_ipv4 ? ip_hdr(skb)->tos :
85 (ipv6_hdr(skb)->priority << 4) +
86 (ipv6_hdr(skb)->flow_lbl[0] >> 4);
87
88 enc_type = ERSPAN_ENCAP_NOVLAN;
89
90 /* If mirrored packet has vlan tag, extract tci and
91 * perserve vlan header in the mirrored frame.
92 */
93 if (eth->h_proto == htons(ETH_P_8021Q)) {
94 qp = (struct qtag_prefix *)(skb->data + 2 * ETH_ALEN);
95 vlan_tci = ntohs(qp->tci);
96 enc_type = ERSPAN_ENCAP_INFRAME;
97 }
98
99 skb_push(skb, sizeof(*ershdr));
100 ershdr = (struct erspanhdr *)skb->data;
101 memset(ershdr, 0, sizeof(*ershdr));
102
103 ershdr->ver_vlan = htons((vlan_tci & VLAN_MASK) |
104 (ERSPAN_VERSION << VER_OFFSET));
105 ershdr->session_id = htons((u16)(ntohl(id) & ID_MASK) |
106 ((tos_to_cos(tos) << COS_OFFSET) & COS_MASK) |
107 (enc_type << EN_OFFSET & EN_MASK) |
108 ((truncate << T_OFFSET) & T_MASK));
109 ershdr->md.index = htonl(index & INDEX_MASK);
110}
111
84e54fe0 112#endif