2 * Copyright (c) 2007 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Sepherosa Ziehau <sepherosa@gmail.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * $DragonFly: src/sys/net/dummynet/ip_dummynet_glue.c,v 1.1 2007/11/16 02:45:45 sephe Exp $
37 #include <sys/param.h>
39 #include <sys/msgport.h>
42 #include <net/if_var.h>
43 #include <net/route.h>
44 #include <net/ethernet.h>
45 #include <net/netisr.h>
46 #include <net/netmsg2.h>
48 #include <netinet/in.h>
49 #include <netinet/in_var.h>
50 #include <netinet/ip.h>
51 #include <netinet/ip_var.h>
53 #include <net/dummynet/ip_dummynet.h>
55 static void ip_dn_ether_output(struct netmsg *);
56 static void ip_dn_ether_demux(struct netmsg *);
57 static void ip_dn_ip_input(struct netmsg *);
58 static void ip_dn_ip_output(struct netmsg *);
60 static void ip_dn_freepkt_dispatch(struct netmsg *);
61 static void ip_dn_dispatch(struct netmsg *);
63 static void ip_dn_freepkt(struct dn_pkt *);
65 ip_dn_io_t *ip_dn_io_ptr;
69 ip_dn_queue(struct mbuf *m)
71 struct netmsg_packet *nmp;
74 KASSERT(m->m_type != MT_TAG, ("mbuf contains old style tag!\n"));
76 nmp = &m->m_hdr.mh_netmsg;
77 netmsg_init(&nmp->nm_netmsg, &netisr_apanic_rport, 0,
81 port = cpu_portfn(ip_dn_cpu);
82 lwkt_sendmsg(port, &nmp->nm_netmsg.nm_lmsg);
86 ip_dn_packet_free(struct dn_pkt *pkt)
88 struct netmsg_packet *nmp;
90 struct mbuf *m = pkt->dn_m;
92 KASSERT(m->m_type != MT_TAG, ("mbuf contains old style tag!\n"));
94 if (pkt->cpuid == mycpuid) {
99 nmp = &m->m_hdr.mh_netmsg;
100 netmsg_init(&nmp->nm_netmsg, &netisr_apanic_rport, 0,
101 ip_dn_freepkt_dispatch);
104 port = cpu_portfn(pkt->cpuid);
105 lwkt_sendmsg(port, &nmp->nm_netmsg.nm_lmsg);
109 ip_dn_packet_redispatch(struct dn_pkt *pkt)
111 static const netisr_fn_t dispatches[DN_TO_MAX] = {
112 [DN_TO_IP_OUT] = ip_dn_ip_output,
113 [DN_TO_IP_IN] = ip_dn_ip_input,
114 [DN_TO_ETH_DEMUX] = ip_dn_ether_demux,
115 [DN_TO_ETH_OUT] = ip_dn_ether_output
118 struct netmsg_packet *nmp;
120 netisr_fn_t dispatch;
124 dir = (pkt->dn_flags & DN_FLAGS_DIR_MASK);
125 KASSERT(dir < DN_TO_MAX,
126 ("unknown dummynet redispatch dir %d\n", dir));
128 dispatch = dispatches[dir];
129 KASSERT(dispatch != NULL,
130 ("unsupported dummynet redispatch dir %d\n", dir));
133 KASSERT(m->m_type != MT_TAG, ("mbuf contains old style tag!\n"));
135 nmp = &m->m_hdr.mh_netmsg;
136 netmsg_init(&nmp->nm_netmsg, &netisr_apanic_rport, 0, dispatch);
139 port = cpu_portfn(pkt->cpuid);
140 lwkt_sendmsg(port, &nmp->nm_netmsg.nm_lmsg);
144 ip_dn_freepkt(struct dn_pkt *pkt)
146 struct rtentry *rt = pkt->ro.ro_rt;
148 /* Unreference route entry */
150 if (rt->rt_refcnt <= 0) { /* XXX assert? */
151 kprintf("-- warning, refcnt now %ld, decreasing\n",
157 /* Unreference packet private data */
158 if (pkt->dn_unref_priv)
159 pkt->dn_unref_priv(pkt->dn_priv);
161 /* Free the parent mbuf, this will free 'pkt' as well */
166 ip_dn_freepkt_dispatch(struct netmsg *nmsg)
168 struct netmsg_packet *nmp;
173 nmp = (struct netmsg_packet *)nmsg;
176 mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
177 pkt = m_tag_data(mtag);
179 KASSERT(pkt->cpuid == mycpuid,
180 ("%s: dummynet packet was delivered to wrong cpu! "
181 "target cpuid %d, mycpuid %d\n", __func__,
182 pkt->cpuid, mycpuid));
188 ip_dn_dispatch(struct netmsg *nmsg)
190 struct netmsg_packet *nmp;
195 KASSERT(ip_dn_cpu == mycpuid,
196 ("%s: dummynet packet was delivered to wrong cpu! "
197 "dummynet cpuid %d, mycpuid %d\n", __func__,
198 ip_dn_cpu, mycpuid));
200 nmp = (struct netmsg_packet *)nmsg;
203 if (DUMMYNET_LOADED) {
204 if (ip_dn_io_ptr(m) == 0)
209 * ip_dn_io_ptr() failed or dummynet(4) is not loaded
211 mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
212 pkt = m_tag_data(mtag);
213 ip_dn_packet_free(pkt);
217 ip_dn_ip_output(struct netmsg *nmsg)
219 struct netmsg_packet *nmp;
224 ip_dn_unref_priv_t unref_priv;
227 nmp = (struct netmsg_packet *)nmsg;
230 mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
231 KKASSERT(mtag != NULL);
232 KKASSERT(m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED);
234 pkt = m_tag_data(mtag);
235 KASSERT(pkt->cpuid == mycpuid,
236 ("%s: dummynet packet was delivered to wrong cpu! "
237 "target cpuid %d, mycpuid %d\n", __func__,
238 pkt->cpuid, mycpuid));
239 KASSERT((pkt->dn_flags & DN_FLAGS_DIR_MASK) == DN_TO_IP_OUT,
240 ("wrong direction %d, should be %d\n",
241 (pkt->dn_flags & DN_FLAGS_DIR_MASK), DN_TO_IP_OUT));
244 unref_priv = pkt->dn_unref_priv;
247 if (rt != NULL && !(rt->rt_flags & RTF_UP)) {
249 * Recorded rtentry is gone, when the packet
256 ip_output(pkt->dn_m, NULL, NULL, 0, NULL, NULL);
259 if (rt->rt_refcnt <= 0) { /* XXX assert? */
260 kprintf("-- warning, refcnt now %ld, decreasing\n",
270 ip_dn_ip_input(struct netmsg *nmsg)
272 struct netmsg_packet *nmp;
276 ip_dn_unref_priv_t unref_priv;
279 nmp = (struct netmsg_packet *)nmsg;
282 mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
283 KKASSERT(mtag != NULL);
284 KKASSERT(m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED);
286 pkt = m_tag_data(mtag);
287 KASSERT(pkt->cpuid == mycpuid,
288 ("%s: dummynet packet was delivered to wrong cpu! "
289 "target cpuid %d, mycpuid %d\n", __func__,
290 pkt->cpuid, mycpuid));
291 KASSERT(pkt->ro.ro_rt == NULL,
292 ("route entry is not NULL for ip_input\n"));
293 KASSERT((pkt->dn_flags & DN_FLAGS_DIR_MASK) == DN_TO_IP_IN,
294 ("wrong direction %d, should be %d\n",
295 (pkt->dn_flags & DN_FLAGS_DIR_MASK), DN_TO_IP_IN));
298 unref_priv = pkt->dn_unref_priv;
307 ip_dn_ether_demux(struct netmsg *nmsg)
309 struct netmsg_packet *nmp;
313 struct ether_header *eh;
314 ip_dn_unref_priv_t unref_priv;
317 nmp = (struct netmsg_packet *)nmsg;
320 mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
321 KKASSERT(mtag != NULL);
322 KKASSERT(m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED);
324 pkt = m_tag_data(mtag);
325 KASSERT(pkt->cpuid == mycpuid,
326 ("%s: dummynet packet was delivered to wrong cpu! "
327 "target cpuid %d, mycpuid %d\n", __func__,
328 pkt->cpuid, mycpuid));
329 KASSERT(pkt->ro.ro_rt == NULL,
330 ("route entry is not NULL for ether_demux\n"));
331 KASSERT((pkt->dn_flags & DN_FLAGS_DIR_MASK) == DN_TO_ETH_DEMUX,
332 ("wrong direction %d, should be %d\n",
333 (pkt->dn_flags & DN_FLAGS_DIR_MASK), DN_TO_ETH_DEMUX));
336 unref_priv = pkt->dn_unref_priv;
338 if (m->m_len < ETHER_HDR_LEN &&
339 (m = m_pullup(m, ETHER_HDR_LEN)) == NULL) {
340 kprintf("%s: pullup fail, dropping pkt\n", __func__);
345 * Same as ether_input, make eh be a pointer into the mbuf
347 eh = mtod(m, struct ether_header *);
348 m_adj(m, ETHER_HDR_LEN);
349 ether_demux(NULL, eh, m);
356 ip_dn_ether_output(struct netmsg *nmsg)
358 struct netmsg_packet *nmp;
362 ip_dn_unref_priv_t unref_priv;
365 nmp = (struct netmsg_packet *)nmsg;
368 mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
369 KKASSERT(mtag != NULL);
370 KKASSERT(m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED);
372 pkt = m_tag_data(mtag);
373 KASSERT(pkt->cpuid == mycpuid,
374 ("%s: dummynet packet was delivered to wrong cpu! "
375 "target cpuid %d, mycpuid %d\n", __func__,
376 pkt->cpuid, mycpuid));
377 KASSERT(pkt->ro.ro_rt == NULL,
378 ("route entry is not NULL for ether_output_frame\n"));
379 KASSERT((pkt->dn_flags & DN_FLAGS_DIR_MASK) == DN_TO_ETH_OUT,
380 ("wrong direction %d, should be %d\n",
381 (pkt->dn_flags & DN_FLAGS_DIR_MASK), DN_TO_ETH_OUT));
384 unref_priv = pkt->dn_unref_priv;
386 ether_output_frame(pkt->ifp, m);