aboutsummaryrefslogtreecommitdiffstats
path: root/net/mpls
diff options
context:
space:
mode:
authorRobert Shearman <rshearma@brocade.com>2015-08-06 06:04:56 -0400
committerDavid S. Miller <davem@davemloft.net>2015-08-10 01:51:42 -0400
commit118d5234636ca3718f47ca2c8a3b117c19dfdffd (patch)
tree165c54e4e2079c7dab2446535f1e1510df0de783 /net/mpls
parentd74a790d5237e7f56677030d932bc4f37ec36c92 (diff)
mpls: Enforce payload type of traffic sent using explicit NULL
RFC 4182 s2 states that if an IPv4 Explicit NULL label is the only label on the stack, then after popping the resulting packet must be treated as a IPv4 packet and forwarded based on the IPv4 header. The same is true for IPv6 Explicit NULL with an IPv6 packet following. Therefore, when installing the IPv4/IPv6 Explicit NULL label routes, add an attribute that specifies the expected payload type for use at forwarding time for determining the type of the encapsulated packet instead of inspecting the first nibble of the packet. Signed-off-by: Robert Shearman <rshearma@brocade.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/mpls')
-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 }