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
31 * $DragonFly: src/sys/netproto/mpls/mpls_output.c,v 1.2 2008/08/05 15:11:32 nant Exp $
34 #include <sys/param.h>
36 #include <sys/systm.h>
38 #include <net/if_var.h>
40 #include <netinet/ip.h>
42 #include <netproto/mpls/mpls.h>
43 #include <netproto/mpls/mpls_var.h>
45 static int mpls_push(struct mbuf
**, mpls_label_t
,
46 mpls_s_t
, mpls_exp_t
, mpls_ttl_t
);
47 static int mpls_swap(struct mbuf
*, mpls_label_t
);
48 static int mpls_pop(struct mbuf
*, mpls_s_t
*);
51 mpls_output(struct mbuf
*m
, struct rtentry
*rt
)
53 struct sockaddr_mpls
*smpls
= NULL
;
62 * Check if we are coming from an MPLS routing table lookup.
63 * The rt_key of this rtentry will have a family AF_MPLS if so.
65 stackempty
= rt_key(rt
)->sa_family
!= AF_MPLS
? 1 : 0;
67 switch (rt_key(rt
)->sa_family
) {
69 ip
= mtod(m
, struct ip
*);
75 for (i
=0; i
< MPLS_MAXLOPS
&& rt
->rt_shim
[i
] != NULL
; ++i
) {
76 smpls
= (struct sockaddr_mpls
*)rt
->rt_shim
[i
];
77 switch (smpls
->smpls_op
) {
80 ntohl(smpls
->smpls_label
),
82 * If we are the first label push, then
83 * set the bottom-of-stack bit.
85 (stackempty
&& i
== 0) ? 1 : 0,
91 m
->m_flags
|= M_MPLSLABELED
;
95 * Operation is only permmited if label stack
100 KKASSERT(m
->m_flags
& M_MPLSLABELED
);
101 error
= mpls_swap(m
, ntohl(smpls
->smpls_label
));
107 * Operation is only permmited if label stack
112 KKASSERT(m
->m_flags
& M_MPLSLABELED
);
113 error
= mpls_pop(m
, &stackempty
);
117 * If we are popping out the last label then
118 * mark the mbuf as ~M_MPLSLABELED.
121 m
->m_flags
&= ~M_MPLSLABELED
;
124 /* Unknown label operation */
133 * Returns FALSE if no further output processing required.
136 mpls_output_process(struct mbuf
*m
, struct rtentry
*rt
)
140 /* Does this route have MPLS label operations? */
141 if (!(rt
->rt_flags
& RTF_MPLSOPS
))
144 error
= mpls_output(m
, rt
);
154 mpls_push(struct mbuf
**m
, mpls_label_t label
, mpls_s_t s
, mpls_exp_t exp
, mpls_ttl_t ttl
) {
156 u_int32_t buf
= 0; /* Silence warning */
158 M_PREPEND(*m
, sizeof(struct mpls
), MB_DONTWAIT
);
162 MPLS_SET_LABEL(buf
, label
);
163 MPLS_SET_STACK(buf
, s
);
164 MPLS_SET_EXP(buf
, exp
);
165 MPLS_SET_TTL(buf
, ttl
);
166 mpls
= mtod(*m
, struct mpls
*);
167 mpls
->mpls_shim
= htonl(buf
);
173 mpls_swap(struct mbuf
*m
, mpls_label_t label
) {
178 if (m
->m_len
< sizeof(struct mpls
) &&
179 (m
= m_pullup(m
, sizeof(struct mpls
))) == NULL
)
182 mpls
= mtod(m
, struct mpls
*);
183 buf
= ntohl(mpls
->mpls_shim
);
186 /* XXX: should send icmp ttl expired. */
187 mplsstat
.mplss_ttlexpired
++;
190 MPLS_SET_LABEL(buf
, label
);
191 MPLS_SET_TTL(buf
, ttl
); /* XXX tunnel mode: uniform, pipe, short pipe */
192 mpls
->mpls_shim
= htonl(buf
);
198 mpls_pop(struct mbuf
*m
, mpls_s_t
*sbit
) {
202 if (m
->m_len
< sizeof(struct mpls
)) {
203 m
= m_pullup(m
, sizeof(struct mpls
));
207 mpls
= mtod(m
, struct mpls
*);
208 buf
= ntohl(mpls
->mpls_shim
);
209 *sbit
= MPLS_STACK(buf
);
211 m_adj(m
, sizeof(struct mpls
));