1 /*****************************************************************************
3 * An implementation of the MPLS (MultiProtocol Label
4 * Switching Architecture) for Linux.
7 * James Leu <jleu@mindspring.com>
8 * Ramon Casellas <casellas@infres.enst.fr>
10 * (c) 1999-2004 James Leu <jleu@mindspring.com>
11 * (c) 2003-2004 Ramon Casellas <casellas@infres.enst.fr>
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version
16 * 2 of the License, or (at your option) any later version.
17 ****************************************************************************/
19 #include <linux/autoconf.h>
20 #include <linux/kernel.h>
21 #include <linux/netdevice.h>
23 #include <linux/slab.h>
24 #include <linux/if_ether.h>
25 #include <linux/if_vlan.h>
26 #include <linux/if_arp.h>
27 #include <linux/kobject.h>
37 * mpls_input - Begin labelled packet processing.
38 * @skb: socket buffer, containing the good stuff.
39 * @dev: device that receives the packet.
40 * @pt: packet type (handler) structure.
41 * @label: label value + metadata (type)
42 * @labelspace: incoming labelspace.
46 mpls_input (struct sk_buff
*skb
, struct net_device
*dev
,
47 struct packet_type
*pt
, struct mpls_label
*label
,
50 MPLS_IN_OPCODE_PROTOTYPE(*func
); /* Function Pointer for Opcodes */
51 struct mpls_prot_driver
*prot
= NULL
;
52 struct mpls_nhlfe
*nhlfe
= NULL
; /* Current NHLFE */
53 struct mpls_ilm
*ilm
= NULL
; /* Current ILM */
54 struct mpls_instr
*mi
= NULL
;
55 void *data
= NULL
; /* current data for opcode */
56 int opcode
= 0; /* Current opcode to execute */
57 char *msg
= NULL
; /* Human readable desc. opcode */
65 /* we only hit this case when we have a recursive label
66 * lookup. drop the previous protocol driver, and ilm
68 mpls_proto_release(MPLSCB(skb
)->prot
);
69 mpls_ilm_release(ilm
);
72 MPLS_DEBUG("labelspace=%d,label=%d,exp=%01x,B.O.S=%d,TTL=%d\n",
73 labelspace
, MPLSCB(skb
)->label
, MPLSCB(skb
)->exp
,
74 MPLSCB(skb
)->bos
, MPLSCB(skb
)->ttl
);
76 /* GET a reference to the ilm given this label value/labelspace*/
77 ilm
= mpls_get_ilm_by_label (label
, labelspace
, MPLSCB(skb
)->bos
);
79 MPLS_DEBUG("unknown incoming label, dropping\n");
83 mpls_proto_hold(ilm
->ilm_proto
);
84 MPLSCB(skb
)->prot
= ilm
->ilm_proto
;
86 ilm
->ilm_stats
.packets
++;
87 ilm
->ilm_stats
.bytes
+= skb
->len
;
89 /* Iterate all the opcodes for this ILM */
90 for (mi
= ilm
->ilm_instr
; mi
; mi
= mi
->mi_next
) {
92 opcode
= mi
->mi_opcode
;
93 msg
= mpls_ops
[opcode
].msg
;
94 func
= mpls_ops
[opcode
].in
;
96 MPLS_DEBUG("opcode %s\n",msg
);
98 MPLS_DEBUG("invalid opcode for input: %s\n",msg
);
102 switch (func(&skb
,ilm
,&nhlfe
,data
)) {
103 case MPLS_RESULT_RECURSE
:
104 label
->ml_type
= MPLS_LABEL_GEN
;
105 label
->u
.ml_gen
= MPLSCB(skb
)->label
;
106 goto mpls_input_start
;
107 case MPLS_RESULT_DLV
:
109 case MPLS_RESULT_FWD
:
111 case MPLS_RESULT_DROP
:
112 mpls_proto_release(MPLSCB(skb
)->prot
);
113 goto mpls_input_drop
;
114 case MPLS_RESULT_SUCCESS
:
118 MPLS_DEBUG("finished executing in label program without DLV or FWD\n");
119 mpls_proto_release(MPLSCB(skb
)->prot
);
121 /* fall through to drop */
125 /* proto driver isn't held yet, no need to release it */
128 mpls_ilm_release(ilm
);
130 MPLS_DEBUG("dropped\n");
135 dst_hold(&ilm
->u
.dst
);
136 skb_dst_set(skb
, &ilm
->u
.dst
);
139 * clean up the packet so that protocols like DHCP
140 * will work across a LSP
142 if (ilm
->ilm_fix_hh
) {
143 if (mpls_finish(skb
) == NULL
) {
144 MPLS_DEBUG("unable to finish skb\n");
149 mpls_ilm_release(ilm
);
151 /* ala Cisco, take the lesser of the TTLs
152 * -if propogate TTL was done at the ingress LER, then the
153 * shim TTL will be less the the header TTL
154 * -if no propogate TTL was done as the ingress LER, a
155 * default TTL was placed in the shim, which makes the
156 * entire length of the LSP look like one hop to traceroute.
157 * As long as the default value placed in the shim is
158 * significantly larger then the TTL in the header, then
159 * traceroute will work fine. If not, then traceroute
160 * will continualy show the egress of the LSP as the
161 * next hop in the path.
164 if (MPLSCB(skb
)->ttl
< MPLSCB(skb
)->prot
->get_ttl(skb
)) {
165 MPLSCB(skb
)->prot
->set_ttl(skb
, MPLSCB(skb
)->ttl
);
168 /* we're done with the PDU, it now goes to another layer for handling
169 * it is safe to release the protocol driver now
171 mpls_proto_release(MPLSCB(skb
)->prot
);
173 MPLS_DEBUG("delivering\n");
179 mpls_ilm_release (ilm
);
181 if (MPLSCB(skb
)->ttl
<= 1) {
182 printk("TTL exceeded\n");
184 prot
= MPLSCB(skb
)->prot
;
185 retval
= prot
->ttl_expired(&skb
);
186 mpls_proto_release(prot
);
191 /* otherwise prot->ttl_expired() must have modified the
192 * skb and want it to be forwarded down the LSP
196 (MPLSCB(skb
)->ttl
)--;
198 dst_hold(&nhlfe
->u
.dst
);
199 skb_dst_set(skb
, &nhlfe
->u
.dst
);
201 /* mpls_switch() does a mpls_proto_release() */
203 MPLS_DEBUG("switching\n");
209 * mpls_skb_recv - Main MPLS packet receive function.
210 * @skb : socket buffer, containing the good stuff.
211 * @dev : device that receives the packet.
212 * @pt : packet type handler.
218 struct net_device
*dev
,
219 struct packet_type
*pt
,
220 struct net_device
*orig
)
223 int result
= NET_RX_DROP
;
224 struct mpls_label label
;
225 struct mpls_interface
*mip
= mpls_get_if_info(dev
->ifindex
);
228 MPLS_DEBUG_CALL(mpls_skb_dump(skb
));
230 if (skb
->pkt_type
== PACKET_OTHERHOST
)
233 if (!(skb
= skb_share_check (skb
, GFP_ATOMIC
)))
236 if (!pskb_may_pull (skb
, MPLS_SHIM_SIZE
))
239 labelspace
= mip
? mip
->labelspace
: -1;
240 if (unlikely(labelspace
< 0)) {
241 MPLS_DEBUG("unicast packet recv on if. w/o labelspace (%s) - packet dropped\n",dev
->name
);
245 memset(MPLSCB(skb
), 0, sizeof(*MPLSCB(skb
)));
246 memset(&label
, 0, sizeof(label
));
247 MPLSCB(skb
)->top_of_stack
= skb
->data
;
249 mpls_opcode_peek (skb
);
251 /* we need the label struct for when we support ATM and FR */
257 case ARPHRD_LOOPBACK
:
260 label
.ml_type
= MPLS_LABEL_GEN
;
261 label
.u
.ml_gen
= MPLSCB(skb
)->label
;
264 printk("Unknown IfType(%08x) for MPLS\n",dev
->type
);
268 if (mpls_input (skb
,dev
,pt
,&label
,labelspace
))
271 result
= dst_input(skb
);
273 MPLS_DEBUG("exit(%d)\n",result
);
277 /* increment some err counter */
281 MPLS_DEBUG("exit(DROP)\n");
290 * mpls_skb_recv_mc - Main Multicast MPLS packet receive function.
291 * @skb : socket buffer, containing the good stuff.
292 * @dev : device that receives the packet.
293 * @pt : packet handler. (MPLS UC)
296 int mpls_skb_recv_mc (
298 struct net_device
*dev
,
299 struct packet_type
*pt
,
300 struct net_device
*orig
)
303 MPLS_DEBUG("Not implemented\n");