2727/* This maximum ha length copied from the definition of struct neighbour */
2828#define MAX_VIA_ALEN (ALIGN(MAX_ADDR_LEN, sizeof(unsigned long)))
2929
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+
3041struct mpls_route { /* next hop label forwarding entry */
3142 struct net_device __rcu * rt_dev ;
3243 struct rcu_head rt_rcu ;
3344 u32 rt_label [MAX_NEW_LABELS ];
3445 u8 rt_protocol ; /* routing protocol that set this entry */
46+ u8 rt_payload_type ;
3547 u8 rt_labels ;
3648 u8 rt_via_alen ;
3749 u8 rt_via_table ;
@@ -96,16 +108,8 @@ EXPORT_SYMBOL_GPL(mpls_pkt_too_big);
96108static bool mpls_egress (struct mpls_route * rt , struct sk_buff * skb ,
97109 struct mpls_entry_decoded dec )
98110{
99- /* RFC4385 and RFC5586 encode other packets in mpls such that
100- * they don't conflict with the ip version number, making
101- * decoding by examining the ip version correct in everything
102- * except for the strangest cases.
103- *
104- * The strange cases if we choose to support them will require
105- * manual configuration.
106- */
107- struct iphdr * hdr4 ;
108- bool success = true;
111+ enum mpls_payload_type payload_type ;
112+ bool success = false;
109113
110114 /* The IPv4 code below accesses through the IPv4 header
111115 * checksum, which is 12 bytes into the packet.
@@ -120,23 +124,32 @@ static bool mpls_egress(struct mpls_route *rt, struct sk_buff *skb,
120124 if (!pskb_may_pull (skb , 12 ))
121125 return false;
122126
123- /* Use ip_hdr to find the ip protocol version */
124- hdr4 = ip_hdr (skb );
125- if (hdr4 -> version == 4 ) {
127+ payload_type = rt -> rt_payload_type ;
128+ if (payload_type == MPT_UNSPEC )
129+ payload_type = ip_hdr (skb )-> version ;
130+
131+ switch (payload_type ) {
132+ case MPT_IPV4 : {
133+ struct iphdr * hdr4 = ip_hdr (skb );
126134 skb -> protocol = htons (ETH_P_IP );
127135 csum_replace2 (& hdr4 -> check ,
128136 htons (hdr4 -> ttl << 8 ),
129137 htons (dec .ttl << 8 ));
130138 hdr4 -> ttl = dec .ttl ;
139+ success = true;
140+ break ;
131141 }
132- else if ( hdr4 -> version == 6 ) {
142+ case MPT_IPV6 : {
133143 struct ipv6hdr * hdr6 = ipv6_hdr (skb );
134144 skb -> protocol = htons (ETH_P_IPV6 );
135145 hdr6 -> hop_limit = dec .ttl ;
146+ success = true;
147+ break ;
136148 }
137- else
138- /* version 0 and version 1 are used by pseudo wires */
139- success = false;
149+ case MPT_UNSPEC :
150+ break ;
151+ }
152+
140153 return success ;
141154}
142155
@@ -255,16 +268,17 @@ static const struct nla_policy rtm_mpls_policy[RTA_MAX+1] = {
255268};
256269
257270struct mpls_route_config {
258- u32 rc_protocol ;
259- u32 rc_ifindex ;
260- u16 rc_via_table ;
261- u16 rc_via_alen ;
262- u8 rc_via [MAX_VIA_ALEN ];
263- u32 rc_label ;
264- u32 rc_output_labels ;
265- u32 rc_output_label [MAX_NEW_LABELS ];
266- u32 rc_nlflags ;
267- struct nl_info rc_nlinfo ;
271+ u32 rc_protocol ;
272+ u32 rc_ifindex ;
273+ u16 rc_via_table ;
274+ u16 rc_via_alen ;
275+ u8 rc_via [MAX_VIA_ALEN ];
276+ u32 rc_label ;
277+ u32 rc_output_labels ;
278+ u32 rc_output_label [MAX_NEW_LABELS ];
279+ u32 rc_nlflags ;
280+ enum mpls_payload_type rc_payload_type ;
281+ struct nl_info rc_nlinfo ;
268282};
269283
270284static struct mpls_route * mpls_rt_alloc (size_t alen )
@@ -493,6 +507,7 @@ static int mpls_route_add(struct mpls_route_config *cfg)
493507 rt -> rt_label [i ] = cfg -> rc_output_label [i ];
494508 rt -> rt_protocol = cfg -> rc_protocol ;
495509 RCU_INIT_POINTER (rt -> rt_dev , dev );
510+ rt -> rt_payload_type = cfg -> rc_payload_type ;
496511 rt -> rt_via_table = cfg -> rc_via_table ;
497512 memcpy (rt -> rt_via , cfg -> rc_via , cfg -> rc_via_alen );
498513
@@ -1047,6 +1062,7 @@ static int resize_platform_label_table(struct net *net, size_t limit)
10471062 goto nort0 ;
10481063 RCU_INIT_POINTER (rt0 -> rt_dev , lo );
10491064 rt0 -> rt_protocol = RTPROT_KERNEL ;
1065+ rt0 -> rt_payload_type = MPT_IPV4 ;
10501066 rt0 -> rt_via_table = NEIGH_LINK_TABLE ;
10511067 memcpy (rt0 -> rt_via , lo -> dev_addr , lo -> addr_len );
10521068 }
@@ -1057,6 +1073,7 @@ static int resize_platform_label_table(struct net *net, size_t limit)
10571073 goto nort2 ;
10581074 RCU_INIT_POINTER (rt2 -> rt_dev , lo );
10591075 rt2 -> rt_protocol = RTPROT_KERNEL ;
1076+ rt2 -> rt_payload_type = MPT_IPV6 ;
10601077 rt2 -> rt_via_table = NEIGH_LINK_TABLE ;
10611078 memcpy (rt2 -> rt_via , lo -> dev_addr , lo -> addr_len );
10621079 }
0 commit comments