2 * Copyright (c) 2007 The DragonFly Project. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
14 * 3. Neither the name of The DragonFly Project nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific, prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/param.h>
34 #include <sys/systm.h>
36 #include <net/if_var.h>
38 #include <netinet/ip.h>
40 #include <netproto/mpls/mpls.h>
41 #include <netproto/mpls/mpls_var.h>
43 static int mpls_push(struct mbuf
**, mpls_label_t
,
44 mpls_s_t
, mpls_exp_t
, mpls_ttl_t
);
45 static int mpls_swap(struct mbuf
*, mpls_label_t
);
46 static int mpls_pop(struct mbuf
*, mpls_s_t
*);
49 mpls_output(struct mbuf
*m
, struct rtentry
*rt
)
51 struct sockaddr_mpls
*smpls
= NULL
;
60 * Check if we are coming from an MPLS routing table lookup.
61 * The rt_key of this rtentry will have a family AF_MPLS if so.
63 stackempty
= rt_key(rt
)->sa_family
!= AF_MPLS
? 1 : 0;
65 switch (rt_key(rt
)->sa_family
) {
67 ip
= mtod(m
, struct ip
*);
73 for (i
=0; i
< MPLS_MAXLOPS
&& rt
->rt_shim
[i
] != NULL
; ++i
) {
74 smpls
= (struct sockaddr_mpls
*)rt
->rt_shim
[i
];
75 switch (smpls
->smpls_op
) {
78 ntohl(smpls
->smpls_label
),
80 * If we are the first label push, then
81 * set the bottom-of-stack bit.
83 (stackempty
&& i
== 0) ? 1 : 0,
89 m
->m_flags
|= M_MPLSLABELED
;
93 * Operation is only permmited if label stack
98 KKASSERT(m
->m_flags
& M_MPLSLABELED
);
99 error
= mpls_swap(m
, ntohl(smpls
->smpls_label
));
105 * Operation is only permmited if label stack
110 KKASSERT(m
->m_flags
& M_MPLSLABELED
);
111 error
= mpls_pop(m
, &stackempty
);
115 * If we are popping out the last label then
116 * mark the mbuf as ~M_MPLSLABELED.
119 m
->m_flags
&= ~M_MPLSLABELED
;
122 /* Unknown label operation */
131 * Returns FALSE if no further output processing required.
134 mpls_output_process(struct mbuf
*m
, struct rtentry
*rt
)
138 /* Does this route have MPLS label operations? */
139 if (!(rt
->rt_flags
& RTF_MPLSOPS
))
142 error
= mpls_output(m
, rt
);
152 mpls_push(struct mbuf
**m
, mpls_label_t label
, mpls_s_t s
, mpls_exp_t exp
, mpls_ttl_t ttl
) {
154 u_int32_t buf
= 0; /* Silence warning */
156 M_PREPEND(*m
, sizeof(struct mpls
), M_NOWAIT
);
160 MPLS_SET_LABEL(buf
, label
);
161 MPLS_SET_STACK(buf
, s
);
162 MPLS_SET_EXP(buf
, exp
);
163 MPLS_SET_TTL(buf
, ttl
);
164 mpls
= mtod(*m
, struct mpls
*);
165 mpls
->mpls_shim
= htonl(buf
);
171 mpls_swap(struct mbuf
*m
, mpls_label_t label
) {
176 if (m
->m_len
< sizeof(struct mpls
) &&
177 (m
= m_pullup(m
, sizeof(struct mpls
))) == NULL
)
180 mpls
= mtod(m
, struct mpls
*);
181 buf
= ntohl(mpls
->mpls_shim
);
184 /* XXX: should send icmp ttl expired. */
185 mplsstat
.mplss_ttlexpired
++;
188 MPLS_SET_LABEL(buf
, label
);
189 MPLS_SET_TTL(buf
, ttl
); /* XXX tunnel mode: uniform, pipe, short pipe */
190 mpls
->mpls_shim
= htonl(buf
);
196 mpls_pop(struct mbuf
*m
, mpls_s_t
*sbit
) {
200 if (m
->m_len
< sizeof(struct mpls
)) {
201 m
= m_pullup(m
, sizeof(struct mpls
));
205 mpls
= mtod(m
, struct mpls
*);
206 buf
= ntohl(mpls
->mpls_shim
);
207 *sbit
= MPLS_STACK(buf
);
209 m_adj(m
, sizeof(struct mpls
));