mpls: allow TTL propagation to IP packets to be configured
[linux-2.6-block.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 enum mpls_ttl_propagation {
94         MPLS_TTL_PROP_DEFAULT,
95         MPLS_TTL_PROP_ENABLED,
96         MPLS_TTL_PROP_DISABLED,
97 };
98
99 /* The route, nexthops and vias are stored together in the same memory
100  * block:
101  *
102  * +----------------------+
103  * | mpls_route           |
104  * +----------------------+
105  * | mpls_nh 0            |
106  * +----------------------+
107  * | ...                  |
108  * +----------------------+
109  * | mpls_nh n-1          |
110  * +----------------------+
111  * | alignment padding    |
112  * +----------------------+
113  * | via[rt_max_alen] 0   |
114  * +----------------------+
115  * | ...                  |
116  * +----------------------+
117  * | via[rt_max_alen] n-1 |
118  * +----------------------+
119  */
120 struct mpls_route { /* next hop label forwarding entry */
121         struct rcu_head         rt_rcu;
122         u8                      rt_protocol;
123         u8                      rt_payload_type;
124         u8                      rt_max_alen;
125         u8                      rt_ttl_propagate;
126         unsigned int            rt_nhn;
127         unsigned int            rt_nhn_alive;
128         struct mpls_nh          rt_nh[0];
129 };
130
131 #define for_nexthops(rt) {                                              \
132         int nhsel; struct mpls_nh *nh;                  \
133         for (nhsel = 0, nh = (rt)->rt_nh;                               \
134              nhsel < (rt)->rt_nhn;                                      \
135              nh++, nhsel++)
136
137 #define change_nexthops(rt) {                                           \
138         int nhsel; struct mpls_nh *nh;                          \
139         for (nhsel = 0, nh = (struct mpls_nh *)((rt)->rt_nh);   \
140              nhsel < (rt)->rt_nhn;                                      \
141              nh++, nhsel++)
142
143 #define endfor_nexthops(rt) }
144
145 static inline struct mpls_shim_hdr mpls_entry_encode(u32 label, unsigned ttl, unsigned tc, bool bos)
146 {
147         struct mpls_shim_hdr result;
148         result.label_stack_entry =
149                 cpu_to_be32((label << MPLS_LS_LABEL_SHIFT) |
150                             (tc << MPLS_LS_TC_SHIFT) |
151                             (bos ? (1 << MPLS_LS_S_SHIFT) : 0) |
152                             (ttl << MPLS_LS_TTL_SHIFT));
153         return result;
154 }
155
156 static inline struct mpls_entry_decoded mpls_entry_decode(struct mpls_shim_hdr *hdr)
157 {
158         struct mpls_entry_decoded result;
159         unsigned entry = be32_to_cpu(hdr->label_stack_entry);
160
161         result.label = (entry & MPLS_LS_LABEL_MASK) >> MPLS_LS_LABEL_SHIFT;
162         result.ttl = (entry & MPLS_LS_TTL_MASK) >> MPLS_LS_TTL_SHIFT;
163         result.tc =  (entry & MPLS_LS_TC_MASK) >> MPLS_LS_TC_SHIFT;
164         result.bos = (entry & MPLS_LS_S_MASK) >> MPLS_LS_S_SHIFT;
165
166         return result;
167 }
168
169 static inline struct mpls_dev *mpls_dev_get(const struct net_device *dev)
170 {
171         return rcu_dereference_rtnl(dev->mpls_ptr);
172 }
173
174 int nla_put_labels(struct sk_buff *skb, int attrtype,  u8 labels,
175                    const u32 label[]);
176 int nla_get_labels(const struct nlattr *nla, u32 max_labels, u8 *labels,
177                    u32 label[]);
178 int nla_get_via(const struct nlattr *nla, u8 *via_alen, u8 *via_table,
179                 u8 via[]);
180 bool mpls_output_possible(const struct net_device *dev);
181 unsigned int mpls_dev_mtu(const struct net_device *dev);
182 bool mpls_pkt_too_big(const struct sk_buff *skb, unsigned int mtu);
183 void mpls_stats_inc_outucastpkts(struct net_device *dev,
184                                  const struct sk_buff *skb);
185
186 #endif /* MPLS_INTERNAL_H */