1 /* mpls6.c: IPv6 MPLS protocol driver.
3 * Copyright (C) 2003 David S. Miller (davem@redhat.com)
6 * JLEU: Add ICMP handling stubs
8 * Change nexthop resolve signature
9 * JLEU: Added mpls6_cache_flush()
10 * JLEU: un/register reserved labels in fini/init
11 * JLEU: remove sysfs print routin
14 #include <linux/module.h>
15 #include <linux/socket.h>
16 #include <linux/skbuff.h>
17 #include <linux/in6.h>
18 #include <linux/init.h>
19 #include <linux/seq_file.h>
20 #include <net/dsfield.h>
21 #include <net/neighbour.h>
23 #include <net/ip6_route.h>
24 #include <net/ip6_fib.h>
28 MODULE_LICENSE("GPL");
30 extern int ipv6_rcv(struct sk_buff
*skb
, struct net_device
*dev
, struct packet_type
*pt
, struct net_device
*orig_dev
);
32 static void mpls6_cache_flush(struct net
*net
)
34 fib6_run_gc((unsigned long)0, net
);
37 static void mpls6_set_ttl(struct sk_buff
*skb
, int ttl
)
39 /*ipv6_hdr(skb)->hop_limit; RCAS*/
40 ipv6_hdr(skb
)->hop_limit
= ttl
;
43 static int mpls6_get_ttl(struct sk_buff
*skb
)
45 return ipv6_hdr(skb
)->hop_limit
;
48 static void mpls6_change_dsfield(struct sk_buff
*skb
, int ds
)
50 ipv6_change_dsfield(ipv6_hdr(skb
), 0x3, ds
);
53 static int mpls6_get_dsfield(struct sk_buff
*skb
)
55 return ipv6_get_dsfield(ipv6_hdr(skb
));
58 /* Policy decision, several options:
61 * 2) Pops all MPLS headers, use resulting upper-layer
62 * protocol packet to generate ICMP.
63 * 3) Walk down MPLS headers to upper-layer header,
64 * generate ICMP using that and then prepend
65 * IDENTICAL MPLS header stack to ICMP packet.
67 * Problem with #2 is that there may be no route to
68 * upper-level packet source for us to use. (f.e. we
69 * are switching VPN packets that we have no routes to).
71 * Option #3 should work even in those cases, because it
72 * is more likely that egress of this MPLS path knows how
73 * to route such packets back to source. It should also
74 * not be susceptible to loops in MPLS fabric, since one
75 * never responds to ICMP with ICMP. It is deliberate
76 * assumption made about upper-layer protocol.
78 static int mpls6_ttl_expired(struct sk_buff
**skb
)
83 static int mpls6_mtu_exceeded(struct sk_buff
**skb
, int mtu
)
85 return MPLS_RESULT_DROP
;
88 static int mpls6_local_deliver(struct sk_buff
*skb
)
90 skb
->protocol
= htons(ETH_P_IPV6
);
91 memset(skb
->cb
, 0, sizeof(skb
->cb
));
92 dst_release(skb_dst(skb
));
93 skb_dst_set(skb
, NULL
);
94 return ipv6_rcv(skb
, skb
->dev
, NULL
, skb
->dev
);
97 static int mpls6_nexthop_resolve(struct neighbour
**np
, struct sockaddr
*sock_addr
, struct net_device
*dev
)
99 struct sockaddr_in6
*addr
= (struct sockaddr_in6
*) sock_addr
;
100 struct flowi fl
= { .oif
= dev
->ifindex
,
101 .nl_u
= { .ip6_u
= {.daddr
= addr
->sin6_addr
} } };
102 struct dst_entry
*dst
;
105 if (addr
->sin6_family
!= AF_INET6
)
108 dst
= ip6_route_output(&init_net
, NULL
, &fl
);
115 *np
= neigh_clone(dst
->neighbour
);
123 static struct mpls_prot_driver mpls6_driver
= {
126 .ethertype
= __constant_htons(ETH_P_IPV6
),
127 .cache_flush
= mpls6_cache_flush
,
128 .set_ttl
= mpls6_set_ttl
,
129 .get_ttl
= mpls6_get_ttl
,
130 .change_dsfield
= mpls6_change_dsfield
,
131 .get_dsfield
= mpls6_get_dsfield
,
132 .ttl_expired
= mpls6_ttl_expired
,
133 .mtu_exceeded
= mpls6_mtu_exceeded
,
134 .local_deliver
= mpls6_local_deliver
,
135 .nexthop_resolve
= mpls6_nexthop_resolve
,
136 .owner
= THIS_MODULE
,
139 static int __init
mpls6_init(void)
141 struct mpls_instr_elem instr
[2];
142 struct mpls_label ml
;
143 struct mpls_ilm
*ilm
;
144 int result
= mpls_proto_add(&mpls6_driver
);
146 printk("MPLS: IPv6 over MPLS support\n");
151 ml
.ml_type
= MPLS_LABEL_GEN
;
152 ml
.u
.ml_gen
= MPLS_IPV6_EXPLICIT_NULL
;
154 instr
[0].mir_direction
= MPLS_IN
;
155 instr
[0].mir_opcode
= MPLS_OP_POP
;
156 instr
[1].mir_direction
= MPLS_IN
;
157 instr
[1].mir_opcode
= MPLS_OP_DLV
;
159 ilm
= mpls_ilm_dst_alloc(0, &ml
, AF_INET6
, instr
, 2);
163 result
= mpls_add_reserved_label(MPLS_IPV6_EXPLICIT_NULL
, ilm
);
165 ilm
->u
.dst
.obsolete
= 1;
166 dst_free(&ilm
->u
.dst
);
173 static void __exit
mpls6_fini(void)
175 struct mpls_ilm
*ilm
= mpls_del_reserved_label(MPLS_IPV6_EXPLICIT_NULL
);
176 mpls_proto_remove(&mpls6_driver
);
179 mpls_ilm_release(ilm
);
180 ilm
->u
.dst
.obsolete
= 1;
181 call_rcu(&ilm
->u
.dst
.rcu_head
, dst_rcu_free
);
185 module_init(mpls6_init
);
186 module_exit(mpls6_fini
);