xref: /openbmc/linux/net/mpls/internal.h (revision 74ce1896)
1 #ifndef MPLS_INTERNAL_H
2 #define MPLS_INTERNAL_H
3 #include <net/mpls.h>
4 
5 /* put a reasonable limit on the number of labels
6  * we will accept from userspace
7  */
8 #define MAX_NEW_LABELS 30
9 
10 struct mpls_entry_decoded {
11 	u32 label;
12 	u8 ttl;
13 	u8 tc;
14 	u8 bos;
15 };
16 
17 struct mpls_pcpu_stats {
18 	struct mpls_link_stats	stats;
19 	struct u64_stats_sync	syncp;
20 };
21 
22 struct mpls_dev {
23 	int				input_enabled;
24 	struct net_device		*dev;
25 	struct mpls_pcpu_stats __percpu	*stats;
26 
27 	struct ctl_table_header		*sysctl;
28 	struct rcu_head			rcu;
29 };
30 
31 #if BITS_PER_LONG == 32
32 
33 #define MPLS_INC_STATS_LEN(mdev, len, pkts_field, bytes_field)		\
34 	do {								\
35 		__typeof__(*(mdev)->stats) *ptr =			\
36 			raw_cpu_ptr((mdev)->stats);			\
37 		local_bh_disable();					\
38 		u64_stats_update_begin(&ptr->syncp);			\
39 		ptr->stats.pkts_field++;				\
40 		ptr->stats.bytes_field += (len);			\
41 		u64_stats_update_end(&ptr->syncp);			\
42 		local_bh_enable();					\
43 	} while (0)
44 
45 #define MPLS_INC_STATS(mdev, field)					\
46 	do {								\
47 		__typeof__(*(mdev)->stats) *ptr =			\
48 			raw_cpu_ptr((mdev)->stats);			\
49 		local_bh_disable();					\
50 		u64_stats_update_begin(&ptr->syncp);			\
51 		ptr->stats.field++;					\
52 		u64_stats_update_end(&ptr->syncp);			\
53 		local_bh_enable();					\
54 	} while (0)
55 
56 #else
57 
58 #define MPLS_INC_STATS_LEN(mdev, len, pkts_field, bytes_field)		\
59 	do {								\
60 		this_cpu_inc((mdev)->stats->stats.pkts_field);		\
61 		this_cpu_add((mdev)->stats->stats.bytes_field, (len));	\
62 	} while (0)
63 
64 #define MPLS_INC_STATS(mdev, field)			\
65 	this_cpu_inc((mdev)->stats->stats.field)
66 
67 #endif
68 
69 struct sk_buff;
70 
71 #define LABEL_NOT_SPECIFIED (1 << 20)
72 
73 /* This maximum ha length copied from the definition of struct neighbour */
74 #define VIA_ALEN_ALIGN sizeof(unsigned long)
75 #define MAX_VIA_ALEN (ALIGN(MAX_ADDR_LEN, VIA_ALEN_ALIGN))
76 
77 enum mpls_payload_type {
78 	MPT_UNSPEC, /* IPv4 or IPv6 */
79 	MPT_IPV4 = 4,
80 	MPT_IPV6 = 6,
81 
82 	/* Other types not implemented:
83 	 *  - Pseudo-wire with or without control word (RFC4385)
84 	 *  - GAL (RFC5586)
85 	 */
86 };
87 
88 struct mpls_nh { /* next hop label forwarding entry */
89 	struct net_device __rcu *nh_dev;
90 
91 	/* nh_flags is accessed under RCU in the packet path; it is
92 	 * modified handling netdev events with rtnl lock held
93 	 */
94 	unsigned int		nh_flags;
95 	u8			nh_labels;
96 	u8			nh_via_alen;
97 	u8			nh_via_table;
98 	u8			nh_reserved1;
99 
100 	u32			nh_label[0];
101 };
102 
103 /* offset of via from beginning of mpls_nh */
104 #define MPLS_NH_VIA_OFF(num_labels) \
105 		ALIGN(sizeof(struct mpls_nh) + (num_labels) * sizeof(u32), \
106 		      VIA_ALEN_ALIGN)
107 
108 /* all nexthops within a route have the same size based on the
109  * max number of labels and max via length across all nexthops
110  */
111 #define MPLS_NH_SIZE(num_labels, max_via_alen)		\
112 		(MPLS_NH_VIA_OFF((num_labels)) +	\
113 		ALIGN((max_via_alen), VIA_ALEN_ALIGN))
114 
115 enum mpls_ttl_propagation {
116 	MPLS_TTL_PROP_DEFAULT,
117 	MPLS_TTL_PROP_ENABLED,
118 	MPLS_TTL_PROP_DISABLED,
119 };
120 
121 /* The route, nexthops and vias are stored together in the same memory
122  * block:
123  *
124  * +----------------------+
125  * | mpls_route           |
126  * +----------------------+
127  * | mpls_nh 0            |
128  * +----------------------+
129  * | alignment padding    |   4 bytes for odd number of labels
130  * +----------------------+
131  * | via[rt_max_alen] 0   |
132  * +----------------------+
133  * | alignment padding    |   via's aligned on sizeof(unsigned long)
134  * +----------------------+
135  * | ...                  |
136  * +----------------------+
137  * | mpls_nh n-1          |
138  * +----------------------+
139  * | via[rt_max_alen] n-1 |
140  * +----------------------+
141  */
142 struct mpls_route { /* next hop label forwarding entry */
143 	struct rcu_head		rt_rcu;
144 	u8			rt_protocol;
145 	u8			rt_payload_type;
146 	u8			rt_max_alen;
147 	u8			rt_ttl_propagate;
148 	u8			rt_nhn;
149 	/* rt_nhn_alive is accessed under RCU in the packet path; it
150 	 * is modified handling netdev events with rtnl lock held
151 	 */
152 	u8			rt_nhn_alive;
153 	u8			rt_nh_size;
154 	u8			rt_via_offset;
155 	u8			rt_reserved1;
156 	struct mpls_nh		rt_nh[0];
157 };
158 
159 #define for_nexthops(rt) {						\
160 	int nhsel; struct mpls_nh *nh;  u8 *__nh;			\
161 	for (nhsel = 0, nh = (rt)->rt_nh, __nh = (u8 *)((rt)->rt_nh);	\
162 	     nhsel < (rt)->rt_nhn;					\
163 	     __nh += rt->rt_nh_size, nh = (struct mpls_nh *)__nh, nhsel++)
164 
165 #define change_nexthops(rt) {						\
166 	int nhsel; struct mpls_nh *nh; u8 *__nh;			\
167 	for (nhsel = 0, nh = (struct mpls_nh *)((rt)->rt_nh),		\
168 			__nh = (u8 *)((rt)->rt_nh);			\
169 	     nhsel < (rt)->rt_nhn;					\
170 	     __nh += rt->rt_nh_size, nh = (struct mpls_nh *)__nh, nhsel++)
171 
172 #define endfor_nexthops(rt) }
173 
174 static inline struct mpls_shim_hdr mpls_entry_encode(u32 label, unsigned ttl, unsigned tc, bool bos)
175 {
176 	struct mpls_shim_hdr result;
177 	result.label_stack_entry =
178 		cpu_to_be32((label << MPLS_LS_LABEL_SHIFT) |
179 			    (tc << MPLS_LS_TC_SHIFT) |
180 			    (bos ? (1 << MPLS_LS_S_SHIFT) : 0) |
181 			    (ttl << MPLS_LS_TTL_SHIFT));
182 	return result;
183 }
184 
185 static inline struct mpls_entry_decoded mpls_entry_decode(struct mpls_shim_hdr *hdr)
186 {
187 	struct mpls_entry_decoded result;
188 	unsigned entry = be32_to_cpu(hdr->label_stack_entry);
189 
190 	result.label = (entry & MPLS_LS_LABEL_MASK) >> MPLS_LS_LABEL_SHIFT;
191 	result.ttl = (entry & MPLS_LS_TTL_MASK) >> MPLS_LS_TTL_SHIFT;
192 	result.tc =  (entry & MPLS_LS_TC_MASK) >> MPLS_LS_TC_SHIFT;
193 	result.bos = (entry & MPLS_LS_S_MASK) >> MPLS_LS_S_SHIFT;
194 
195 	return result;
196 }
197 
198 static inline struct mpls_dev *mpls_dev_get(const struct net_device *dev)
199 {
200 	return rcu_dereference_rtnl(dev->mpls_ptr);
201 }
202 
203 int nla_put_labels(struct sk_buff *skb, int attrtype,  u8 labels,
204 		   const u32 label[]);
205 int nla_get_labels(const struct nlattr *nla, u8 max_labels, u8 *labels,
206 		   u32 label[], struct netlink_ext_ack *extack);
207 bool mpls_output_possible(const struct net_device *dev);
208 unsigned int mpls_dev_mtu(const struct net_device *dev);
209 bool mpls_pkt_too_big(const struct sk_buff *skb, unsigned int mtu);
210 void mpls_stats_inc_outucastpkts(struct net_device *dev,
211 				 const struct sk_buff *skb);
212 
213 #endif /* MPLS_INTERNAL_H */
214