mpls: multipath route support
[firefly-linux-kernel-4.4.55.git] / net / mpls / internal.h
1 #ifndef MPLS_INTERNAL_H
2 #define MPLS_INTERNAL_H
3
4 struct mpls_shim_hdr {
5         __be32 label_stack_entry;
6 };
7
8 struct mpls_entry_decoded {
9         u32 label;
10         u8 ttl;
11         u8 tc;
12         u8 bos;
13 };
14
15 struct mpls_dev {
16         int                     input_enabled;
17
18         struct ctl_table_header *sysctl;
19         struct rcu_head         rcu;
20 };
21
22 struct sk_buff;
23
24 #define LABEL_NOT_SPECIFIED (1 << 20)
25 #define MAX_NEW_LABELS 2
26
27 /* This maximum ha length copied from the definition of struct neighbour */
28 #define MAX_VIA_ALEN (ALIGN(MAX_ADDR_LEN, sizeof(unsigned long)))
29
30 enum mpls_payload_type {
31         MPT_UNSPEC, /* IPv4 or IPv6 */
32         MPT_IPV4 = 4,
33         MPT_IPV6 = 6,
34
35         /* Other types not implemented:
36          *  - Pseudo-wire with or without control word (RFC4385)
37          *  - GAL (RFC5586)
38          */
39 };
40
41 struct mpls_nh { /* next hop label forwarding entry */
42         struct net_device __rcu *nh_dev;
43         u32                     nh_label[MAX_NEW_LABELS];
44         u8                      nh_labels;
45         u8                      nh_via_alen;
46         u8                      nh_via_table;
47         u8                      nh_via[MAX_VIA_ALEN];
48 };
49
50 struct mpls_route { /* next hop label forwarding entry */
51         struct rcu_head         rt_rcu;
52         u8                      rt_protocol;
53         u8                      rt_payload_type;
54         int                     rt_nhn;
55         struct mpls_nh          rt_nh[0];
56 };
57
58 #define for_nexthops(rt) {                                              \
59         int nhsel; struct mpls_nh *nh;                  \
60         for (nhsel = 0, nh = (rt)->rt_nh;                               \
61              nhsel < (rt)->rt_nhn;                                      \
62              nh++, nhsel++)
63
64 #define change_nexthops(rt) {                                           \
65         int nhsel; struct mpls_nh *nh;                          \
66         for (nhsel = 0, nh = (struct mpls_nh *)((rt)->rt_nh);   \
67              nhsel < (rt)->rt_nhn;                                      \
68              nh++, nhsel++)
69
70 #define endfor_nexthops(rt) }
71
72 static inline struct mpls_shim_hdr *mpls_hdr(const struct sk_buff *skb)
73 {
74         return (struct mpls_shim_hdr *)skb_network_header(skb);
75 }
76
77 static inline struct mpls_shim_hdr mpls_entry_encode(u32 label, unsigned ttl, unsigned tc, bool bos)
78 {
79         struct mpls_shim_hdr result;
80         result.label_stack_entry =
81                 cpu_to_be32((label << MPLS_LS_LABEL_SHIFT) |
82                             (tc << MPLS_LS_TC_SHIFT) |
83                             (bos ? (1 << MPLS_LS_S_SHIFT) : 0) |
84                             (ttl << MPLS_LS_TTL_SHIFT));
85         return result;
86 }
87
88 static inline struct mpls_entry_decoded mpls_entry_decode(struct mpls_shim_hdr *hdr)
89 {
90         struct mpls_entry_decoded result;
91         unsigned entry = be32_to_cpu(hdr->label_stack_entry);
92
93         result.label = (entry & MPLS_LS_LABEL_MASK) >> MPLS_LS_LABEL_SHIFT;
94         result.ttl = (entry & MPLS_LS_TTL_MASK) >> MPLS_LS_TTL_SHIFT;
95         result.tc =  (entry & MPLS_LS_TC_MASK) >> MPLS_LS_TC_SHIFT;
96         result.bos = (entry & MPLS_LS_S_MASK) >> MPLS_LS_S_SHIFT;
97
98         return result;
99 }
100
101 int nla_put_labels(struct sk_buff *skb, int attrtype,  u8 labels,
102                    const u32 label[]);
103 int nla_get_labels(const struct nlattr *nla, u32 max_labels, u8 *labels,
104                    u32 label[]);
105 int nla_get_via(const struct nlattr *nla, u8 *via_alen, u8 *via_table,
106                 u8 via[]);
107 bool mpls_output_possible(const struct net_device *dev);
108 unsigned int mpls_dev_mtu(const struct net_device *dev);
109 bool mpls_pkt_too_big(const struct sk_buff *skb, unsigned int mtu);
110
111 #endif /* MPLS_INTERNAL_H */