]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - net/mpls/internal.h
Merge branch 'for-4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
[karo-tx-linux.git] / net / mpls / internal.h
1 #ifndef MPLS_INTERNAL_H
2 #define MPLS_INTERNAL_H
3 #include <net/mpls.h>
4
5 struct mpls_entry_decoded {
6         u32 label;
7         u8 ttl;
8         u8 tc;
9         u8 bos;
10 };
11
12 struct mpls_pcpu_stats {
13         struct mpls_link_stats  stats;
14         struct u64_stats_sync   syncp;
15 };
16
17 struct mpls_dev {
18         int                             input_enabled;
19         struct net_device               *dev;
20         struct mpls_pcpu_stats __percpu *stats;
21
22         struct ctl_table_header         *sysctl;
23         struct rcu_head                 rcu;
24 };
25
26 #if BITS_PER_LONG == 32
27
28 #define MPLS_INC_STATS_LEN(mdev, len, pkts_field, bytes_field)          \
29         do {                                                            \
30                 __typeof__(*(mdev)->stats) *ptr =                       \
31                         raw_cpu_ptr((mdev)->stats);                     \
32                 local_bh_disable();                                     \
33                 u64_stats_update_begin(&ptr->syncp);                    \
34                 ptr->stats.pkts_field++;                                \
35                 ptr->stats.bytes_field += (len);                        \
36                 u64_stats_update_end(&ptr->syncp);                      \
37                 local_bh_enable();                                      \
38         } while (0)
39
40 #define MPLS_INC_STATS(mdev, field)                                     \
41         do {                                                            \
42                 __typeof__(*(mdev)->stats) *ptr =                       \
43                         raw_cpu_ptr((mdev)->stats);                     \
44                 local_bh_disable();                                     \
45                 u64_stats_update_begin(&ptr->syncp);                    \
46                 ptr->stats.field++;                                     \
47                 u64_stats_update_end(&ptr->syncp);                      \
48                 local_bh_enable();                                      \
49         } while (0)
50
51 #else
52
53 #define MPLS_INC_STATS_LEN(mdev, len, pkts_field, bytes_field)          \
54         do {                                                            \
55                 this_cpu_inc((mdev)->stats->stats.pkts_field);          \
56                 this_cpu_add((mdev)->stats->stats.bytes_field, (len));  \
57         } while (0)
58
59 #define MPLS_INC_STATS(mdev, field)                     \
60         this_cpu_inc((mdev)->stats->stats.field)
61
62 #endif
63
64 struct sk_buff;
65
66 #define LABEL_NOT_SPECIFIED (1 << 20)
67 #define MAX_NEW_LABELS 2
68
69 /* This maximum ha length copied from the definition of struct neighbour */
70 #define VIA_ALEN_ALIGN sizeof(unsigned long)
71 #define MAX_VIA_ALEN (ALIGN(MAX_ADDR_LEN, VIA_ALEN_ALIGN))
72
73 enum mpls_payload_type {
74         MPT_UNSPEC, /* IPv4 or IPv6 */
75         MPT_IPV4 = 4,
76         MPT_IPV6 = 6,
77
78         /* Other types not implemented:
79          *  - Pseudo-wire with or without control word (RFC4385)
80          *  - GAL (RFC5586)
81          */
82 };
83
84 struct mpls_nh { /* next hop label forwarding entry */
85         struct net_device __rcu *nh_dev;
86         unsigned int            nh_flags;
87         u32                     nh_label[MAX_NEW_LABELS];
88         u8                      nh_labels;
89         u8                      nh_via_alen;
90         u8                      nh_via_table;
91 };
92
93 /* The route, nexthops and vias are stored together in the same memory
94  * block:
95  *
96  * +----------------------+
97  * | mpls_route           |
98  * +----------------------+
99  * | mpls_nh 0            |
100  * +----------------------+
101  * | ...                  |
102  * +----------------------+
103  * | mpls_nh n-1          |
104  * +----------------------+
105  * | alignment padding    |
106  * +----------------------+
107  * | via[rt_max_alen] 0   |
108  * +----------------------+
109  * | ...                  |
110  * +----------------------+
111  * | via[rt_max_alen] n-1 |
112  * +----------------------+
113  */
114 struct mpls_route { /* next hop label forwarding entry */
115         struct rcu_head         rt_rcu;
116         u8                      rt_protocol;
117         u8                      rt_payload_type;
118         u8                      rt_max_alen;
119         unsigned int            rt_nhn;
120         unsigned int            rt_nhn_alive;
121         struct mpls_nh          rt_nh[0];
122 };
123
124 #define for_nexthops(rt) {                                              \
125         int nhsel; struct mpls_nh *nh;                  \
126         for (nhsel = 0, nh = (rt)->rt_nh;                               \
127              nhsel < (rt)->rt_nhn;                                      \
128              nh++, nhsel++)
129
130 #define change_nexthops(rt) {                                           \
131         int nhsel; struct mpls_nh *nh;                          \
132         for (nhsel = 0, nh = (struct mpls_nh *)((rt)->rt_nh);   \
133              nhsel < (rt)->rt_nhn;                                      \
134              nh++, nhsel++)
135
136 #define endfor_nexthops(rt) }
137
138 static inline struct mpls_shim_hdr mpls_entry_encode(u32 label, unsigned ttl, unsigned tc, bool bos)
139 {
140         struct mpls_shim_hdr result;
141         result.label_stack_entry =
142                 cpu_to_be32((label << MPLS_LS_LABEL_SHIFT) |
143                             (tc << MPLS_LS_TC_SHIFT) |
144                             (bos ? (1 << MPLS_LS_S_SHIFT) : 0) |
145                             (ttl << MPLS_LS_TTL_SHIFT));
146         return result;
147 }
148
149 static inline struct mpls_entry_decoded mpls_entry_decode(struct mpls_shim_hdr *hdr)
150 {
151         struct mpls_entry_decoded result;
152         unsigned entry = be32_to_cpu(hdr->label_stack_entry);
153
154         result.label = (entry & MPLS_LS_LABEL_MASK) >> MPLS_LS_LABEL_SHIFT;
155         result.ttl = (entry & MPLS_LS_TTL_MASK) >> MPLS_LS_TTL_SHIFT;
156         result.tc =  (entry & MPLS_LS_TC_MASK) >> MPLS_LS_TC_SHIFT;
157         result.bos = (entry & MPLS_LS_S_MASK) >> MPLS_LS_S_SHIFT;
158
159         return result;
160 }
161
162 static inline struct mpls_dev *mpls_dev_get(const struct net_device *dev)
163 {
164         return rcu_dereference_rtnl(dev->mpls_ptr);
165 }
166
167 int nla_put_labels(struct sk_buff *skb, int attrtype,  u8 labels,
168                    const u32 label[]);
169 int nla_get_labels(const struct nlattr *nla, u32 max_labels, u8 *labels,
170                    u32 label[]);
171 int nla_get_via(const struct nlattr *nla, u8 *via_alen, u8 *via_table,
172                 u8 via[]);
173 bool mpls_output_possible(const struct net_device *dev);
174 unsigned int mpls_dev_mtu(const struct net_device *dev);
175 bool mpls_pkt_too_big(const struct sk_buff *skb, unsigned int mtu);
176 void mpls_stats_inc_outucastpkts(struct net_device *dev,
177                                  const struct sk_buff *skb);
178
179 #endif /* MPLS_INTERNAL_H */