aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mpls/af_mpls.c71
1 files changed, 44 insertions, 27 deletions
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index 04306989d054..8c5707db53c5 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -27,11 +27,23 @@
27/* This maximum ha length copied from the definition of struct neighbour */ 27/* This maximum ha length copied from the definition of struct neighbour */
28#define MAX_VIA_ALEN (ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))) 28#define MAX_VIA_ALEN (ALIGN(MAX_ADDR_LEN, sizeof(unsigned long)))
29 29
30enum 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
30struct mpls_route { /* next hop label forwarding entry */ 41struct mpls_route { /* next hop label forwarding entry */
31 struct net_device __rcu *rt_dev; 42 struct net_device __rcu *rt_dev;
32 struct rcu_head rt_rcu; 43 struct rcu_head rt_rcu;
33 u32 rt_label[MAX_NEW_LABELS]; 44 u32 rt_label[MAX_NEW_LABELS];
34 u8 rt_protocol; /* routing protocol that set this entry */ 45 u8 rt_protocol; /* routing protocol that set this entry */
46 u8 rt_payload_type;
35 u8 rt_labels; 47 u8 rt_labels;
36 u8 rt_via_alen; 48 u8 rt_via_alen;
37 u8 rt_via_table; 49 u8 rt_via_table;
@@ -96,16 +108,8 @@ EXPORT_SYMBOL_GPL(mpls_pkt_too_big);
96static bool mpls_egress(struct mpls_route *rt, struct sk_buff *skb, 108static bool mpls_egress(struct mpls_route *rt, struct sk_buff *skb,
97 struct mpls_entry_decoded dec) 109 struct mpls_entry_decoded dec)
98{ 110{
99 /* RFC4385 and RFC5586 encode other packets in mpls such that 111 enum mpls_payload_type payload_type;
100 * they don't conflict with the ip version number, making 112 bool success = false;
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;
109 113
110 /* The IPv4 code below accesses through the IPv4 header 114 /* The IPv4 code below accesses through the IPv4 header
111 * checksum, which is 12 bytes into the packet. 115 * checksum, which is 12 bytes into the packet.
@@ -120,23 +124,32 @@ static bool mpls_egress(struct mpls_route *rt, struct sk_buff *skb,
120 if (!pskb_may_pull(skb, 12)) 124 if (!pskb_may_pull(skb, 12))
121 return false; 125 return false;
122 126
123 /* Use ip_hdr to find the ip protocol version */ 127 payload_type = rt->rt_payload_type;
124 hdr4 = ip_hdr(skb); 128 if (payload_type == MPT_UNSPEC)
125 if (hdr4->version == 4) { 129 payload_type = ip_hdr(skb)->version;
130
131 switch (payload_type) {
132 case MPT_IPV4: {
133 struct iphdr *hdr4 = ip_hdr(skb);
126 skb->protocol = htons(ETH_P_IP); 134 skb->protocol = htons(ETH_P_IP);
127 csum_replace2(&hdr4->check, 135 csum_replace2(&hdr4->check,
128 htons(hdr4->ttl << 8), 136 htons(hdr4->ttl << 8),
129 htons(dec.ttl << 8)); 137 htons(dec.ttl << 8));
130 hdr4->ttl = dec.ttl; 138 hdr4->ttl = dec.ttl;
139 success = true;
140 break;
131 } 141 }
132 else if (hdr4->version == 6) { 142 case MPT_IPV6: {
133 struct ipv6hdr *hdr6 = ipv6_hdr(skb); 143 struct ipv6hdr *hdr6 = ipv6_hdr(skb);
134 skb->protocol = htons(ETH_P_IPV6); 144 skb->protocol = htons(ETH_P_IPV6);
135 hdr6->hop_limit = dec.ttl; 145 hdr6->hop_limit = dec.ttl;
146 success = true;
147 break;
136 } 148 }
137 else 149 case MPT_UNSPEC:
138 /* version 0 and version 1 are used by pseudo wires */ 150 break;
139 success = false; 151 }
152
140 return success; 153 return success;
141} 154}
142 155
@@ -255,16 +268,17 @@ static const struct nla_policy rtm_mpls_policy[RTA_MAX+1] = {
255}; 268};
256 269
257struct mpls_route_config { 270struct mpls_route_config {
258 u32 rc_protocol; 271 u32 rc_protocol;
259 u32 rc_ifindex; 272 u32 rc_ifindex;
260 u16 rc_via_table; 273 u16 rc_via_table;
261 u16 rc_via_alen; 274 u16 rc_via_alen;
262 u8 rc_via[MAX_VIA_ALEN]; 275 u8 rc_via[MAX_VIA_ALEN];
263 u32 rc_label; 276 u32 rc_label;
264 u32 rc_output_labels; 277 u32 rc_output_labels;
265 u32 rc_output_label[MAX_NEW_LABELS]; 278 u32 rc_output_label[MAX_NEW_LABELS];
266 u32 rc_nlflags; 279 u32 rc_nlflags;
267 struct nl_info rc_nlinfo; 280 enum mpls_payload_type rc_payload_type;
281 struct nl_info rc_nlinfo;
268}; 282};
269 283
270static struct mpls_route *mpls_rt_alloc(size_t alen) 284static struct mpls_route *mpls_rt_alloc(size_t alen)
@@ -493,6 +507,7 @@ static int mpls_route_add(struct mpls_route_config *cfg)
493 rt->rt_label[i] = cfg->rc_output_label[i]; 507 rt->rt_label[i] = cfg->rc_output_label[i];
494 rt->rt_protocol = cfg->rc_protocol; 508 rt->rt_protocol = cfg->rc_protocol;
495 RCU_INIT_POINTER(rt->rt_dev, dev); 509 RCU_INIT_POINTER(rt->rt_dev, dev);
510 rt->rt_payload_type = cfg->rc_payload_type;
496 rt->rt_via_table = cfg->rc_via_table; 511 rt->rt_via_table = cfg->rc_via_table;
497 memcpy(rt->rt_via, cfg->rc_via, cfg->rc_via_alen); 512 memcpy(rt->rt_via, cfg->rc_via, cfg->rc_via_alen);
498 513
@@ -1047,6 +1062,7 @@ static int resize_platform_label_table(struct net *net, size_t limit)
1047 goto nort0; 1062 goto nort0;
1048 RCU_INIT_POINTER(rt0->rt_dev, lo); 1063 RCU_INIT_POINTER(rt0->rt_dev, lo);
1049 rt0->rt_protocol = RTPROT_KERNEL; 1064 rt0->rt_protocol = RTPROT_KERNEL;
1065 rt0->rt_payload_type = MPT_IPV4;
1050 rt0->rt_via_table = NEIGH_LINK_TABLE; 1066 rt0->rt_via_table = NEIGH_LINK_TABLE;
1051 memcpy(rt0->rt_via, lo->dev_addr, lo->addr_len); 1067 memcpy(rt0->rt_via, lo->dev_addr, lo->addr_len);
1052 } 1068 }
@@ -1057,6 +1073,7 @@ static int resize_platform_label_table(struct net *net, size_t limit)
1057 goto nort2; 1073 goto nort2;
1058 RCU_INIT_POINTER(rt2->rt_dev, lo); 1074 RCU_INIT_POINTER(rt2->rt_dev, lo);
1059 rt2->rt_protocol = RTPROT_KERNEL; 1075 rt2->rt_protocol = RTPROT_KERNEL;
1076 rt2->rt_payload_type = MPT_IPV6;
1060 rt2->rt_via_table = NEIGH_LINK_TABLE; 1077 rt2->rt_via_table = NEIGH_LINK_TABLE;
1061 memcpy(rt2->rt_via, lo->dev_addr, lo->addr_len); 1078 memcpy(rt2->rt_via, lo->dev_addr, lo->addr_len);
1062 } 1079 }