amd64: declare initializecpu outside of SMP
[dragonfly.git] / sys / netproto / mpls / mpls_output.c
blob06946e3636540cda165b24a1b14d7f7bb9c93a43
1 /*
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
6 * are met:
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
13 * distribution.
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
29 * SUCH DAMAGE.
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>
35 #include <sys/mbuf.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 *);
50 int
51 mpls_output(struct mbuf *m, struct rtentry *rt)
53 struct sockaddr_mpls *smpls = NULL;
54 int error = 0, i;
55 mpls_s_t stackempty;
56 mpls_ttl_t ttl = 255;
57 struct ip *ip;
59 M_ASSERTPKTHDR(m);
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;
66 if (stackempty) {
67 switch (rt_key(rt)->sa_family) {
68 case AF_INET:
69 ip = mtod(m, struct ip *);
70 ttl = ip->ip_ttl;
71 break;
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) {
78 case MPLSLOP_PUSH:
79 error = mpls_push(&m,
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,
87 ttl);
88 if (error)
89 return (error);
90 stackempty = 0;
91 m->m_flags |= M_MPLSLABELED;
92 break;
93 case MPLSLOP_SWAP:
95 * Operation is only permmited if label stack
96 * is not empty.
98 if (stackempty)
99 return (ENOTSUP);
100 KKASSERT(m->m_flags & M_MPLSLABELED);
101 error = mpls_swap(m, ntohl(smpls->smpls_label));
102 if (error)
103 return (error);
104 break;
105 case MPLSLOP_POP:
107 * Operation is only permmited if label stack
108 * is not empty.
110 if (stackempty)
111 return (ENOTSUP);
112 KKASSERT(m->m_flags & M_MPLSLABELED);
113 error = mpls_pop(m, &stackempty);
114 if (error)
115 return (error);
117 * If we are popping out the last label then
118 * mark the mbuf as ~M_MPLSLABELED.
120 if (stackempty)
121 m->m_flags &= ~M_MPLSLABELED;
122 break;
123 default:
124 /* Unknown label operation */
125 return (ENOTSUP);
129 return (error);
133 * Returns FALSE if no further output processing required.
135 boolean_t
136 mpls_output_process(struct mbuf *m, struct rtentry *rt)
138 int error;
140 /* Does this route have MPLS label operations? */
141 if (!(rt->rt_flags & RTF_MPLSOPS))
142 return TRUE;
144 error = mpls_output(m, rt);
145 if (error) {
146 m_freem(m);
147 return FALSE;
150 return TRUE;
153 static int
154 mpls_push(struct mbuf **m, mpls_label_t label, mpls_s_t s, mpls_exp_t exp, mpls_ttl_t ttl) {
155 struct mpls *mpls;
156 u_int32_t buf = 0; /* Silence warning */
158 M_PREPEND(*m, sizeof(struct mpls), MB_DONTWAIT);
159 if (*m == NULL)
160 return (ENOBUFS);
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);
169 return (0);
172 static int
173 mpls_swap(struct mbuf *m, mpls_label_t label) {
174 struct mpls *mpls;
175 u_int32_t buf;
176 mpls_ttl_t ttl;
178 if (m->m_len < sizeof(struct mpls) &&
179 (m = m_pullup(m, sizeof(struct mpls))) == NULL)
180 return (ENOBUFS);
182 mpls = mtod(m, struct mpls *);
183 buf = ntohl(mpls->mpls_shim);
184 ttl = MPLS_TTL(buf);
185 if (--ttl <= 0) {
186 /* XXX: should send icmp ttl expired. */
187 mplsstat.mplss_ttlexpired++;
188 return (ETIMEDOUT);
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);
194 return (0);
197 static int
198 mpls_pop(struct mbuf *m, mpls_s_t *sbit) {
199 struct mpls *mpls;
200 u_int32_t buf;
202 if (m->m_len < sizeof(struct mpls)) {
203 m = m_pullup(m, sizeof(struct mpls));
204 if (m == NULL)
205 return (ENOBUFS);
207 mpls = mtod(m, struct mpls *);
208 buf = ntohl(mpls->mpls_shim);
209 *sbit = MPLS_STACK(buf);
211 m_adj(m, sizeof(struct mpls));
213 return (0);