184a3e25aSSepherosa Ziehau /*
284a3e25aSSepherosa Ziehau * Copyright (c) 2007 The DragonFly Project. All rights reserved.
384a3e25aSSepherosa Ziehau *
484a3e25aSSepherosa Ziehau * This code is derived from software contributed to The DragonFly Project
584a3e25aSSepherosa Ziehau * by Sepherosa Ziehau <sepherosa@gmail.com>
684a3e25aSSepherosa Ziehau *
784a3e25aSSepherosa Ziehau * Redistribution and use in source and binary forms, with or without
884a3e25aSSepherosa Ziehau * modification, are permitted provided that the following conditions
984a3e25aSSepherosa Ziehau * are met:
1084a3e25aSSepherosa Ziehau *
1184a3e25aSSepherosa Ziehau * 1. Redistributions of source code must retain the above copyright
1284a3e25aSSepherosa Ziehau * notice, this list of conditions and the following disclaimer.
1384a3e25aSSepherosa Ziehau * 2. Redistributions in binary form must reproduce the above copyright
1484a3e25aSSepherosa Ziehau * notice, this list of conditions and the following disclaimer in
1584a3e25aSSepherosa Ziehau * the documentation and/or other materials provided with the
1684a3e25aSSepherosa Ziehau * distribution.
1784a3e25aSSepherosa Ziehau * 3. Neither the name of The DragonFly Project nor the names of its
1884a3e25aSSepherosa Ziehau * contributors may be used to endorse or promote products derived
1984a3e25aSSepherosa Ziehau * from this software without specific, prior written permission.
2084a3e25aSSepherosa Ziehau *
2184a3e25aSSepherosa Ziehau * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2284a3e25aSSepherosa Ziehau * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2384a3e25aSSepherosa Ziehau * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2484a3e25aSSepherosa Ziehau * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
2584a3e25aSSepherosa Ziehau * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2684a3e25aSSepherosa Ziehau * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
2784a3e25aSSepherosa Ziehau * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2884a3e25aSSepherosa Ziehau * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2984a3e25aSSepherosa Ziehau * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
3084a3e25aSSepherosa Ziehau * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
3184a3e25aSSepherosa Ziehau * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3284a3e25aSSepherosa Ziehau * SUCH DAMAGE.
3384a3e25aSSepherosa Ziehau */
3484a3e25aSSepherosa Ziehau
3584a3e25aSSepherosa Ziehau #include <sys/param.h>
36329bf5d1SSepherosa Ziehau #include <sys/kernel.h>
37*805c8e8eSzrj #include <sys/malloc.h>
3884a3e25aSSepherosa Ziehau #include <sys/mbuf.h>
3984a3e25aSSepherosa Ziehau #include <sys/msgport.h>
40879652a3SSepherosa Ziehau #include <sys/socketvar.h>
41329bf5d1SSepherosa Ziehau #include <sys/sysctl.h>
4284a3e25aSSepherosa Ziehau
4384a3e25aSSepherosa Ziehau #include <net/if.h>
4484a3e25aSSepherosa Ziehau #include <net/if_var.h>
4584a3e25aSSepherosa Ziehau #include <net/route.h>
4684a3e25aSSepherosa Ziehau #include <net/ethernet.h>
475337421cSSepherosa Ziehau #include <net/netisr2.h>
4884a3e25aSSepherosa Ziehau #include <net/netmsg2.h>
4984a3e25aSSepherosa Ziehau
5084a3e25aSSepherosa Ziehau #include <netinet/in.h>
5184a3e25aSSepherosa Ziehau #include <netinet/in_var.h>
5284a3e25aSSepherosa Ziehau #include <netinet/ip.h>
5384a3e25aSSepherosa Ziehau #include <netinet/ip_var.h>
5484a3e25aSSepherosa Ziehau
5584a3e25aSSepherosa Ziehau #include <net/dummynet/ip_dummynet.h>
5684a3e25aSSepherosa Ziehau
57002c1265SMatthew Dillon static void ip_dn_ether_output(netmsg_t);
58002c1265SMatthew Dillon static void ip_dn_ether_demux(netmsg_t);
59002c1265SMatthew Dillon static void ip_dn_ip_input(netmsg_t);
60002c1265SMatthew Dillon static void ip_dn_ip_output(netmsg_t);
6184a3e25aSSepherosa Ziehau
62002c1265SMatthew Dillon static void ip_dn_sockopt_dispatch(netmsg_t);
63002c1265SMatthew Dillon static void ip_dn_freepkt_dispatch(netmsg_t);
64002c1265SMatthew Dillon static void ip_dn_dispatch(netmsg_t);
6584a3e25aSSepherosa Ziehau
6684a3e25aSSepherosa Ziehau static void ip_dn_freepkt(struct dn_pkt *);
6784a3e25aSSepherosa Ziehau
68879652a3SSepherosa Ziehau static int ip_dn_sockopt_flush(struct sockopt *);
69879652a3SSepherosa Ziehau static int ip_dn_sockopt_get(struct sockopt *);
70879652a3SSepherosa Ziehau static int ip_dn_sockopt_config(struct sockopt *);
71879652a3SSepherosa Ziehau
7284a3e25aSSepherosa Ziehau ip_dn_io_t *ip_dn_io_ptr;
7331ce7747SSepherosa Ziehau ip_dn_ctl_t *ip_dn_ctl_ptr;
7484a3e25aSSepherosa Ziehau int ip_dn_cpu = 0;
7584a3e25aSSepherosa Ziehau
76329bf5d1SSepherosa Ziehau TUNABLE_INT("net.inet.ip.dummynet.cpu", &ip_dn_cpu);
77329bf5d1SSepherosa Ziehau
78329bf5d1SSepherosa Ziehau SYSCTL_NODE(_net_inet_ip, OID_AUTO, dummynet, CTLFLAG_RW, 0, "Dummynet");
79329bf5d1SSepherosa Ziehau SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, cpu, CTLFLAG_RD,
80329bf5d1SSepherosa Ziehau &ip_dn_cpu, 0, "CPU to run dummynet");
81329bf5d1SSepherosa Ziehau
8284a3e25aSSepherosa Ziehau void
ip_dn_queue(struct mbuf * m)8384a3e25aSSepherosa Ziehau ip_dn_queue(struct mbuf *m)
8484a3e25aSSepherosa Ziehau {
8584a3e25aSSepherosa Ziehau struct netmsg_packet *nmp;
8684a3e25aSSepherosa Ziehau lwkt_port_t port;
8784a3e25aSSepherosa Ziehau
88840665f6SSepherosa Ziehau M_ASSERTPKTHDR(m);
89840665f6SSepherosa Ziehau KASSERT(m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED,
90ed20d0e3SSascha Wildner ("mbuf is not tagged for dummynet!"));
9184a3e25aSSepherosa Ziehau
9284a3e25aSSepherosa Ziehau nmp = &m->m_hdr.mh_netmsg;
93002c1265SMatthew Dillon netmsg_init(&nmp->base, NULL, &netisr_apanic_rport,
9448e7b118SMatthew Dillon 0, ip_dn_dispatch);
9584a3e25aSSepherosa Ziehau nmp->nm_packet = m;
9684a3e25aSSepherosa Ziehau
97ec7f7fc8SSepherosa Ziehau port = netisr_cpuport(ip_dn_cpu);
98002c1265SMatthew Dillon lwkt_sendmsg(port, &nmp->base.lmsg);
9984a3e25aSSepherosa Ziehau }
10084a3e25aSSepherosa Ziehau
10184a3e25aSSepherosa Ziehau void
ip_dn_packet_free(struct dn_pkt * pkt)10284a3e25aSSepherosa Ziehau ip_dn_packet_free(struct dn_pkt *pkt)
10384a3e25aSSepherosa Ziehau {
10484a3e25aSSepherosa Ziehau struct netmsg_packet *nmp;
10584a3e25aSSepherosa Ziehau struct mbuf *m = pkt->dn_m;
10684a3e25aSSepherosa Ziehau
107840665f6SSepherosa Ziehau M_ASSERTPKTHDR(m);
108840665f6SSepherosa Ziehau KASSERT(m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED,
109ed20d0e3SSascha Wildner ("mbuf is not tagged for dummynet!"));
11084a3e25aSSepherosa Ziehau
11184a3e25aSSepherosa Ziehau nmp = &m->m_hdr.mh_netmsg;
112002c1265SMatthew Dillon netmsg_init(&nmp->base, NULL, &netisr_apanic_rport,
11348e7b118SMatthew Dillon 0, ip_dn_freepkt_dispatch);
11484a3e25aSSepherosa Ziehau nmp->nm_packet = m;
11584a3e25aSSepherosa Ziehau
116002c1265SMatthew Dillon lwkt_sendmsg(pkt->msgport, &nmp->base.lmsg);
11784a3e25aSSepherosa Ziehau }
11884a3e25aSSepherosa Ziehau
11984a3e25aSSepherosa Ziehau void
ip_dn_packet_redispatch(struct dn_pkt * pkt)12084a3e25aSSepherosa Ziehau ip_dn_packet_redispatch(struct dn_pkt *pkt)
12184a3e25aSSepherosa Ziehau {
12284a3e25aSSepherosa Ziehau static const netisr_fn_t dispatches[DN_TO_MAX] = {
12384a3e25aSSepherosa Ziehau [DN_TO_IP_OUT] = ip_dn_ip_output,
12484a3e25aSSepherosa Ziehau [DN_TO_IP_IN] = ip_dn_ip_input,
12584a3e25aSSepherosa Ziehau [DN_TO_ETH_DEMUX] = ip_dn_ether_demux,
12684a3e25aSSepherosa Ziehau [DN_TO_ETH_OUT] = ip_dn_ether_output
12784a3e25aSSepherosa Ziehau };
12884a3e25aSSepherosa Ziehau
12984a3e25aSSepherosa Ziehau struct netmsg_packet *nmp;
13084a3e25aSSepherosa Ziehau struct mbuf *m;
13184a3e25aSSepherosa Ziehau netisr_fn_t dispatch;
13284a3e25aSSepherosa Ziehau int dir;
13384a3e25aSSepherosa Ziehau
13484a3e25aSSepherosa Ziehau dir = (pkt->dn_flags & DN_FLAGS_DIR_MASK);
13584a3e25aSSepherosa Ziehau KASSERT(dir < DN_TO_MAX,
136ed20d0e3SSascha Wildner ("unknown dummynet redispatch dir %d", dir));
13784a3e25aSSepherosa Ziehau
13884a3e25aSSepherosa Ziehau dispatch = dispatches[dir];
13984a3e25aSSepherosa Ziehau KASSERT(dispatch != NULL,
140ed20d0e3SSascha Wildner ("unsupported dummynet redispatch dir %d", dir));
14184a3e25aSSepherosa Ziehau
14284a3e25aSSepherosa Ziehau m = pkt->dn_m;
143840665f6SSepherosa Ziehau M_ASSERTPKTHDR(m);
144840665f6SSepherosa Ziehau KASSERT(m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED,
145ed20d0e3SSascha Wildner ("mbuf is not tagged for dummynet!"));
14684a3e25aSSepherosa Ziehau
14784a3e25aSSepherosa Ziehau nmp = &m->m_hdr.mh_netmsg;
148002c1265SMatthew Dillon netmsg_init(&nmp->base, NULL, &netisr_apanic_rport, 0, dispatch);
14984a3e25aSSepherosa Ziehau nmp->nm_packet = m;
15084a3e25aSSepherosa Ziehau
151002c1265SMatthew Dillon lwkt_sendmsg(pkt->msgport, &nmp->base.lmsg);
15284a3e25aSSepherosa Ziehau }
15384a3e25aSSepherosa Ziehau
154879652a3SSepherosa Ziehau int
ip_dn_sockopt(struct sockopt * sopt)155879652a3SSepherosa Ziehau ip_dn_sockopt(struct sockopt *sopt)
156879652a3SSepherosa Ziehau {
157879652a3SSepherosa Ziehau int error = 0;
158879652a3SSepherosa Ziehau
159879652a3SSepherosa Ziehau /* Disallow sets in really-really secure mode. */
160879652a3SSepherosa Ziehau if (sopt->sopt_dir == SOPT_SET) {
161879652a3SSepherosa Ziehau if (securelevel >= 3)
162879652a3SSepherosa Ziehau return EPERM;
163879652a3SSepherosa Ziehau }
164879652a3SSepherosa Ziehau
165879652a3SSepherosa Ziehau switch (sopt->sopt_name) {
166879652a3SSepherosa Ziehau case IP_DUMMYNET_GET:
167879652a3SSepherosa Ziehau error = ip_dn_sockopt_get(sopt);
168879652a3SSepherosa Ziehau break;
169879652a3SSepherosa Ziehau
170879652a3SSepherosa Ziehau case IP_DUMMYNET_FLUSH:
171879652a3SSepherosa Ziehau error = ip_dn_sockopt_flush(sopt);
172879652a3SSepherosa Ziehau break;
173879652a3SSepherosa Ziehau
174879652a3SSepherosa Ziehau case IP_DUMMYNET_DEL:
175879652a3SSepherosa Ziehau case IP_DUMMYNET_CONFIGURE:
176879652a3SSepherosa Ziehau error = ip_dn_sockopt_config(sopt);
177879652a3SSepherosa Ziehau break;
178879652a3SSepherosa Ziehau
179879652a3SSepherosa Ziehau default:
180879652a3SSepherosa Ziehau kprintf("%s -- unknown option %d\n", __func__, sopt->sopt_name);
181879652a3SSepherosa Ziehau error = EINVAL;
182879652a3SSepherosa Ziehau break;
183879652a3SSepherosa Ziehau }
184879652a3SSepherosa Ziehau return error;
185879652a3SSepherosa Ziehau }
186879652a3SSepherosa Ziehau
18784a3e25aSSepherosa Ziehau static void
ip_dn_freepkt(struct dn_pkt * pkt)18884a3e25aSSepherosa Ziehau ip_dn_freepkt(struct dn_pkt *pkt)
18984a3e25aSSepherosa Ziehau {
19084a3e25aSSepherosa Ziehau struct rtentry *rt = pkt->ro.ro_rt;
19184a3e25aSSepherosa Ziehau
19284a3e25aSSepherosa Ziehau /* Unreference route entry */
19384a3e25aSSepherosa Ziehau if (rt != NULL) {
19484a3e25aSSepherosa Ziehau if (rt->rt_refcnt <= 0) { /* XXX assert? */
19584a3e25aSSepherosa Ziehau kprintf("-- warning, refcnt now %ld, decreasing\n",
19684a3e25aSSepherosa Ziehau rt->rt_refcnt);
19784a3e25aSSepherosa Ziehau }
19884a3e25aSSepherosa Ziehau RTFREE(rt);
19984a3e25aSSepherosa Ziehau }
20084a3e25aSSepherosa Ziehau
20184a3e25aSSepherosa Ziehau /* Unreference packet private data */
20284a3e25aSSepherosa Ziehau if (pkt->dn_unref_priv)
20384a3e25aSSepherosa Ziehau pkt->dn_unref_priv(pkt->dn_priv);
20484a3e25aSSepherosa Ziehau
20584a3e25aSSepherosa Ziehau /* Free the parent mbuf, this will free 'pkt' as well */
20684a3e25aSSepherosa Ziehau m_freem(pkt->dn_m);
20784a3e25aSSepherosa Ziehau }
20884a3e25aSSepherosa Ziehau
20984a3e25aSSepherosa Ziehau static void
ip_dn_freepkt_dispatch(netmsg_t nmsg)210002c1265SMatthew Dillon ip_dn_freepkt_dispatch(netmsg_t nmsg)
21184a3e25aSSepherosa Ziehau {
21284a3e25aSSepherosa Ziehau struct netmsg_packet *nmp;
21384a3e25aSSepherosa Ziehau struct mbuf *m;
21484a3e25aSSepherosa Ziehau struct m_tag *mtag;
21584a3e25aSSepherosa Ziehau struct dn_pkt *pkt;
21684a3e25aSSepherosa Ziehau
217002c1265SMatthew Dillon nmp = &nmsg->packet;
21884a3e25aSSepherosa Ziehau m = nmp->nm_packet;
219840665f6SSepherosa Ziehau M_ASSERTPKTHDR(m);
220840665f6SSepherosa Ziehau KASSERT(m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED,
221ed20d0e3SSascha Wildner ("mbuf is not tagged for dummynet!"));
22284a3e25aSSepherosa Ziehau
22384a3e25aSSepherosa Ziehau mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
224840665f6SSepherosa Ziehau KKASSERT(mtag != NULL);
22584a3e25aSSepherosa Ziehau
226840665f6SSepherosa Ziehau pkt = m_tag_data(mtag);
22784a3e25aSSepherosa Ziehau KASSERT(pkt->cpuid == mycpuid,
22884a3e25aSSepherosa Ziehau ("%s: dummynet packet was delivered to wrong cpu! "
229ed20d0e3SSascha Wildner "target cpuid %d, mycpuid %d", __func__,
23084a3e25aSSepherosa Ziehau pkt->cpuid, mycpuid));
23184a3e25aSSepherosa Ziehau
23284a3e25aSSepherosa Ziehau ip_dn_freepkt(pkt);
23384a3e25aSSepherosa Ziehau }
23484a3e25aSSepherosa Ziehau
23584a3e25aSSepherosa Ziehau static void
ip_dn_dispatch(netmsg_t nmsg)236002c1265SMatthew Dillon ip_dn_dispatch(netmsg_t nmsg)
23784a3e25aSSepherosa Ziehau {
23884a3e25aSSepherosa Ziehau struct netmsg_packet *nmp;
23984a3e25aSSepherosa Ziehau struct mbuf *m;
24084a3e25aSSepherosa Ziehau struct m_tag *mtag;
24184a3e25aSSepherosa Ziehau struct dn_pkt *pkt;
24284a3e25aSSepherosa Ziehau
24384a3e25aSSepherosa Ziehau KASSERT(ip_dn_cpu == mycpuid,
24484a3e25aSSepherosa Ziehau ("%s: dummynet packet was delivered to wrong cpu! "
245ed20d0e3SSascha Wildner "dummynet cpuid %d, mycpuid %d", __func__,
24684a3e25aSSepherosa Ziehau ip_dn_cpu, mycpuid));
24784a3e25aSSepherosa Ziehau
248002c1265SMatthew Dillon nmp = &nmsg->packet;
24984a3e25aSSepherosa Ziehau m = nmp->nm_packet;
250840665f6SSepherosa Ziehau M_ASSERTPKTHDR(m);
251840665f6SSepherosa Ziehau KASSERT(m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED,
252ed20d0e3SSascha Wildner ("mbuf is not tagged for dummynet!"));
25384a3e25aSSepherosa Ziehau
25484a3e25aSSepherosa Ziehau if (DUMMYNET_LOADED) {
25584a3e25aSSepherosa Ziehau if (ip_dn_io_ptr(m) == 0)
25684a3e25aSSepherosa Ziehau return;
25784a3e25aSSepherosa Ziehau }
25884a3e25aSSepherosa Ziehau
25984a3e25aSSepherosa Ziehau /*
26084a3e25aSSepherosa Ziehau * ip_dn_io_ptr() failed or dummynet(4) is not loaded
26184a3e25aSSepherosa Ziehau */
26284a3e25aSSepherosa Ziehau mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
263840665f6SSepherosa Ziehau KKASSERT(mtag != NULL);
264840665f6SSepherosa Ziehau
26584a3e25aSSepherosa Ziehau pkt = m_tag_data(mtag);
26684a3e25aSSepherosa Ziehau ip_dn_packet_free(pkt);
26784a3e25aSSepherosa Ziehau }
26884a3e25aSSepherosa Ziehau
26984a3e25aSSepherosa Ziehau static void
ip_dn_ip_output(netmsg_t nmsg)270002c1265SMatthew Dillon ip_dn_ip_output(netmsg_t nmsg)
27184a3e25aSSepherosa Ziehau {
27284a3e25aSSepherosa Ziehau struct netmsg_packet *nmp;
27384a3e25aSSepherosa Ziehau struct mbuf *m;
27484a3e25aSSepherosa Ziehau struct m_tag *mtag;
27584a3e25aSSepherosa Ziehau struct dn_pkt *pkt;
27684a3e25aSSepherosa Ziehau struct rtentry *rt;
27784a3e25aSSepherosa Ziehau ip_dn_unref_priv_t unref_priv;
27884a3e25aSSepherosa Ziehau void *priv;
27984a3e25aSSepherosa Ziehau
280002c1265SMatthew Dillon nmp = &nmsg->packet;
28184a3e25aSSepherosa Ziehau m = nmp->nm_packet;
282840665f6SSepherosa Ziehau M_ASSERTPKTHDR(m);
283840665f6SSepherosa Ziehau KASSERT(m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED,
284ed20d0e3SSascha Wildner ("mbuf is not tagged for dummynet!"));
28584a3e25aSSepherosa Ziehau
28684a3e25aSSepherosa Ziehau mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
28784a3e25aSSepherosa Ziehau KKASSERT(mtag != NULL);
28884a3e25aSSepherosa Ziehau
28984a3e25aSSepherosa Ziehau pkt = m_tag_data(mtag);
29084a3e25aSSepherosa Ziehau KASSERT(pkt->cpuid == mycpuid,
29184a3e25aSSepherosa Ziehau ("%s: dummynet packet was delivered to wrong cpu! "
292ed20d0e3SSascha Wildner "target cpuid %d, mycpuid %d", __func__,
29384a3e25aSSepherosa Ziehau pkt->cpuid, mycpuid));
29484a3e25aSSepherosa Ziehau KASSERT((pkt->dn_flags & DN_FLAGS_DIR_MASK) == DN_TO_IP_OUT,
295ed20d0e3SSascha Wildner ("wrong direction %d, should be %d",
29684a3e25aSSepherosa Ziehau (pkt->dn_flags & DN_FLAGS_DIR_MASK), DN_TO_IP_OUT));
29784a3e25aSSepherosa Ziehau
29884a3e25aSSepherosa Ziehau priv = pkt->dn_priv;
29984a3e25aSSepherosa Ziehau unref_priv = pkt->dn_unref_priv;
30084a3e25aSSepherosa Ziehau rt = pkt->ro.ro_rt;
30184a3e25aSSepherosa Ziehau
30284a3e25aSSepherosa Ziehau if (rt != NULL && !(rt->rt_flags & RTF_UP)) {
30384a3e25aSSepherosa Ziehau /*
30484a3e25aSSepherosa Ziehau * Recorded rtentry is gone, when the packet
30584a3e25aSSepherosa Ziehau * was on delay line.
30684a3e25aSSepherosa Ziehau */
30784a3e25aSSepherosa Ziehau ip_dn_freepkt(pkt);
30884a3e25aSSepherosa Ziehau return;
30984a3e25aSSepherosa Ziehau }
31084a3e25aSSepherosa Ziehau
3114d935b66SSepherosa Ziehau ip_output(pkt->dn_m, NULL, NULL, pkt->flags, NULL, NULL);
3124d935b66SSepherosa Ziehau /* 'rt' will be freed in ip_output */
31384a3e25aSSepherosa Ziehau
31484a3e25aSSepherosa Ziehau if (unref_priv)
31584a3e25aSSepherosa Ziehau unref_priv(priv);
31684a3e25aSSepherosa Ziehau }
31784a3e25aSSepherosa Ziehau
31884a3e25aSSepherosa Ziehau static void
ip_dn_ip_input(netmsg_t nmsg)319002c1265SMatthew Dillon ip_dn_ip_input(netmsg_t nmsg)
32084a3e25aSSepherosa Ziehau {
32184a3e25aSSepherosa Ziehau struct netmsg_packet *nmp;
32284a3e25aSSepherosa Ziehau struct mbuf *m;
32384a3e25aSSepherosa Ziehau struct m_tag *mtag;
32484a3e25aSSepherosa Ziehau struct dn_pkt *pkt;
32584a3e25aSSepherosa Ziehau ip_dn_unref_priv_t unref_priv;
32684a3e25aSSepherosa Ziehau void *priv;
3277376bec4SSepherosa Ziehau struct ip *ip;
32884a3e25aSSepherosa Ziehau
329002c1265SMatthew Dillon nmp = &nmsg->packet;
33084a3e25aSSepherosa Ziehau m = nmp->nm_packet;
331840665f6SSepherosa Ziehau M_ASSERTPKTHDR(m);
332840665f6SSepherosa Ziehau KASSERT(m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED,
333ed20d0e3SSascha Wildner ("mbuf is not tagged for dummynet!"));
33484a3e25aSSepherosa Ziehau
33584a3e25aSSepherosa Ziehau mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
33684a3e25aSSepherosa Ziehau KKASSERT(mtag != NULL);
33784a3e25aSSepherosa Ziehau
33884a3e25aSSepherosa Ziehau pkt = m_tag_data(mtag);
33984a3e25aSSepherosa Ziehau KASSERT(pkt->cpuid == mycpuid,
34084a3e25aSSepherosa Ziehau ("%s: dummynet packet was delivered to wrong cpu! "
341ed20d0e3SSascha Wildner "target cpuid %d, mycpuid %d", __func__,
34284a3e25aSSepherosa Ziehau pkt->cpuid, mycpuid));
34384a3e25aSSepherosa Ziehau KASSERT(pkt->ro.ro_rt == NULL,
344ed20d0e3SSascha Wildner ("route entry is not NULL for ip_input"));
34584a3e25aSSepherosa Ziehau KASSERT((pkt->dn_flags & DN_FLAGS_DIR_MASK) == DN_TO_IP_IN,
346ed20d0e3SSascha Wildner ("wrong direction %d, should be %d",
34784a3e25aSSepherosa Ziehau (pkt->dn_flags & DN_FLAGS_DIR_MASK), DN_TO_IP_IN));
34884a3e25aSSepherosa Ziehau
34984a3e25aSSepherosa Ziehau priv = pkt->dn_priv;
35084a3e25aSSepherosa Ziehau unref_priv = pkt->dn_unref_priv;
35184a3e25aSSepherosa Ziehau
3527376bec4SSepherosa Ziehau KKASSERT(m->m_len >= sizeof(*ip));
3537376bec4SSepherosa Ziehau
35484a3e25aSSepherosa Ziehau ip_input(m);
35584a3e25aSSepherosa Ziehau
35684a3e25aSSepherosa Ziehau if (unref_priv)
35784a3e25aSSepherosa Ziehau unref_priv(priv);
35884a3e25aSSepherosa Ziehau }
35984a3e25aSSepherosa Ziehau
36084a3e25aSSepherosa Ziehau static void
ip_dn_ether_demux(netmsg_t nmsg)361002c1265SMatthew Dillon ip_dn_ether_demux(netmsg_t nmsg)
36284a3e25aSSepherosa Ziehau {
36384a3e25aSSepherosa Ziehau struct netmsg_packet *nmp;
36484a3e25aSSepherosa Ziehau struct mbuf *m;
36584a3e25aSSepherosa Ziehau struct m_tag *mtag;
36684a3e25aSSepherosa Ziehau struct dn_pkt *pkt;
36784a3e25aSSepherosa Ziehau ip_dn_unref_priv_t unref_priv;
36884a3e25aSSepherosa Ziehau void *priv;
36984a3e25aSSepherosa Ziehau
370002c1265SMatthew Dillon nmp = &nmsg->packet;
37184a3e25aSSepherosa Ziehau m = nmp->nm_packet;
372840665f6SSepherosa Ziehau M_ASSERTPKTHDR(m);
373840665f6SSepherosa Ziehau KASSERT(m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED,
374ed20d0e3SSascha Wildner ("mbuf is not tagged for dummynet!"));
37584a3e25aSSepherosa Ziehau
37684a3e25aSSepherosa Ziehau mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
37784a3e25aSSepherosa Ziehau KKASSERT(mtag != NULL);
37884a3e25aSSepherosa Ziehau
37984a3e25aSSepherosa Ziehau pkt = m_tag_data(mtag);
38084a3e25aSSepherosa Ziehau KASSERT(pkt->cpuid == mycpuid,
38184a3e25aSSepherosa Ziehau ("%s: dummynet packet was delivered to wrong cpu! "
382ed20d0e3SSascha Wildner "target cpuid %d, mycpuid %d", __func__,
38384a3e25aSSepherosa Ziehau pkt->cpuid, mycpuid));
38484a3e25aSSepherosa Ziehau KASSERT(pkt->ro.ro_rt == NULL,
385ed20d0e3SSascha Wildner ("route entry is not NULL for ether_demux"));
38684a3e25aSSepherosa Ziehau KASSERT((pkt->dn_flags & DN_FLAGS_DIR_MASK) == DN_TO_ETH_DEMUX,
387ed20d0e3SSascha Wildner ("wrong direction %d, should be %d",
38884a3e25aSSepherosa Ziehau (pkt->dn_flags & DN_FLAGS_DIR_MASK), DN_TO_ETH_DEMUX));
38984a3e25aSSepherosa Ziehau
39084a3e25aSSepherosa Ziehau priv = pkt->dn_priv;
39184a3e25aSSepherosa Ziehau unref_priv = pkt->dn_unref_priv;
39284a3e25aSSepherosa Ziehau
393d781b904SSepherosa Ziehau /*
394d781b904SSepherosa Ziehau * Make sure that ether header is contiguous
395d781b904SSepherosa Ziehau */
39684a3e25aSSepherosa Ziehau if (m->m_len < ETHER_HDR_LEN &&
39784a3e25aSSepherosa Ziehau (m = m_pullup(m, ETHER_HDR_LEN)) == NULL) {
39884a3e25aSSepherosa Ziehau kprintf("%s: pullup fail, dropping pkt\n", __func__);
39984a3e25aSSepherosa Ziehau goto back;
40084a3e25aSSepherosa Ziehau }
4015bad48b5SSepherosa Ziehau ether_demux_oncpu(m->m_pkthdr.rcvif, m);
40284a3e25aSSepherosa Ziehau back:
40384a3e25aSSepherosa Ziehau if (unref_priv)
40484a3e25aSSepherosa Ziehau unref_priv(priv);
40584a3e25aSSepherosa Ziehau }
40684a3e25aSSepherosa Ziehau
40784a3e25aSSepherosa Ziehau static void
ip_dn_ether_output(netmsg_t nmsg)408002c1265SMatthew Dillon ip_dn_ether_output(netmsg_t nmsg)
40984a3e25aSSepherosa Ziehau {
41084a3e25aSSepherosa Ziehau struct netmsg_packet *nmp;
41184a3e25aSSepherosa Ziehau struct mbuf *m;
41284a3e25aSSepherosa Ziehau struct m_tag *mtag;
41384a3e25aSSepherosa Ziehau struct dn_pkt *pkt;
41484a3e25aSSepherosa Ziehau ip_dn_unref_priv_t unref_priv;
41584a3e25aSSepherosa Ziehau void *priv;
41684a3e25aSSepherosa Ziehau
417002c1265SMatthew Dillon nmp = &nmsg->packet;
41884a3e25aSSepherosa Ziehau m = nmp->nm_packet;
419840665f6SSepherosa Ziehau M_ASSERTPKTHDR(m);
420840665f6SSepherosa Ziehau KASSERT(m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED,
421ed20d0e3SSascha Wildner ("mbuf is not tagged for dummynet!"));
42284a3e25aSSepherosa Ziehau
42384a3e25aSSepherosa Ziehau mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
42484a3e25aSSepherosa Ziehau KKASSERT(mtag != NULL);
42584a3e25aSSepherosa Ziehau
42684a3e25aSSepherosa Ziehau pkt = m_tag_data(mtag);
42784a3e25aSSepherosa Ziehau KASSERT(pkt->cpuid == mycpuid,
42884a3e25aSSepherosa Ziehau ("%s: dummynet packet was delivered to wrong cpu! "
429ed20d0e3SSascha Wildner "target cpuid %d, mycpuid %d", __func__,
43084a3e25aSSepherosa Ziehau pkt->cpuid, mycpuid));
43184a3e25aSSepherosa Ziehau KASSERT(pkt->ro.ro_rt == NULL,
432ed20d0e3SSascha Wildner ("route entry is not NULL for ether_output_frame"));
43384a3e25aSSepherosa Ziehau KASSERT((pkt->dn_flags & DN_FLAGS_DIR_MASK) == DN_TO_ETH_OUT,
434ed20d0e3SSascha Wildner ("wrong direction %d, should be %d",
43584a3e25aSSepherosa Ziehau (pkt->dn_flags & DN_FLAGS_DIR_MASK), DN_TO_ETH_OUT));
43684a3e25aSSepherosa Ziehau
43784a3e25aSSepherosa Ziehau priv = pkt->dn_priv;
43884a3e25aSSepherosa Ziehau unref_priv = pkt->dn_unref_priv;
43984a3e25aSSepherosa Ziehau
44084a3e25aSSepherosa Ziehau ether_output_frame(pkt->ifp, m);
44184a3e25aSSepherosa Ziehau
44284a3e25aSSepherosa Ziehau if (unref_priv)
44384a3e25aSSepherosa Ziehau unref_priv(priv);
44484a3e25aSSepherosa Ziehau }
445879652a3SSepherosa Ziehau
446879652a3SSepherosa Ziehau static void
ip_dn_sockopt_dispatch(netmsg_t nmsg)447002c1265SMatthew Dillon ip_dn_sockopt_dispatch(netmsg_t nmsg)
448879652a3SSepherosa Ziehau {
449002c1265SMatthew Dillon lwkt_msg *msg = &nmsg->lmsg;
450879652a3SSepherosa Ziehau struct dn_sopt *dn_sopt = msg->u.ms_resultp;
451879652a3SSepherosa Ziehau int error;
452879652a3SSepherosa Ziehau
453879652a3SSepherosa Ziehau KASSERT(ip_dn_cpu == mycpuid,
454879652a3SSepherosa Ziehau ("%s: dummynet sockopt is done on wrong cpu! "
455ed20d0e3SSascha Wildner "dummynet cpuid %d, mycpuid %d", __func__,
456879652a3SSepherosa Ziehau ip_dn_cpu, mycpuid));
457879652a3SSepherosa Ziehau
458879652a3SSepherosa Ziehau if (DUMMYNET_LOADED)
459879652a3SSepherosa Ziehau error = ip_dn_ctl_ptr(dn_sopt);
460879652a3SSepherosa Ziehau else
461879652a3SSepherosa Ziehau error = ENOPROTOOPT;
462879652a3SSepherosa Ziehau lwkt_replymsg(msg, error);
463879652a3SSepherosa Ziehau }
464879652a3SSepherosa Ziehau
465879652a3SSepherosa Ziehau static int
ip_dn_sockopt_flush(struct sockopt * sopt)466879652a3SSepherosa Ziehau ip_dn_sockopt_flush(struct sockopt *sopt)
467879652a3SSepherosa Ziehau {
468879652a3SSepherosa Ziehau struct dn_sopt dn_sopt;
469002c1265SMatthew Dillon struct netmsg_base smsg;
470879652a3SSepherosa Ziehau
471879652a3SSepherosa Ziehau bzero(&dn_sopt, sizeof(dn_sopt));
472879652a3SSepherosa Ziehau dn_sopt.dn_sopt_name = sopt->sopt_name;
473879652a3SSepherosa Ziehau
47448e7b118SMatthew Dillon netmsg_init(&smsg, NULL, &curthread->td_msgport,
47548e7b118SMatthew Dillon 0, ip_dn_sockopt_dispatch);
476002c1265SMatthew Dillon smsg.lmsg.u.ms_resultp = &dn_sopt;
477ec7f7fc8SSepherosa Ziehau lwkt_domsg(netisr_cpuport(ip_dn_cpu), &smsg.lmsg, 0);
478879652a3SSepherosa Ziehau
479002c1265SMatthew Dillon return smsg.lmsg.ms_error;
480879652a3SSepherosa Ziehau }
481879652a3SSepherosa Ziehau
482879652a3SSepherosa Ziehau static int
ip_dn_sockopt_get(struct sockopt * sopt)483879652a3SSepherosa Ziehau ip_dn_sockopt_get(struct sockopt *sopt)
484879652a3SSepherosa Ziehau {
485879652a3SSepherosa Ziehau struct dn_sopt dn_sopt;
486002c1265SMatthew Dillon struct netmsg_base smsg;
487879652a3SSepherosa Ziehau int error;
488879652a3SSepherosa Ziehau
489879652a3SSepherosa Ziehau bzero(&dn_sopt, sizeof(dn_sopt));
490879652a3SSepherosa Ziehau dn_sopt.dn_sopt_name = sopt->sopt_name;
491879652a3SSepherosa Ziehau
49248e7b118SMatthew Dillon netmsg_init(&smsg, NULL, &curthread->td_msgport,
49348e7b118SMatthew Dillon 0, ip_dn_sockopt_dispatch);
494002c1265SMatthew Dillon smsg.lmsg.u.ms_resultp = &dn_sopt;
495ec7f7fc8SSepherosa Ziehau lwkt_domsg(netisr_cpuport(ip_dn_cpu), &smsg.lmsg, 0);
496879652a3SSepherosa Ziehau
497002c1265SMatthew Dillon error = smsg.lmsg.ms_error;
498879652a3SSepherosa Ziehau if (error) {
499879652a3SSepherosa Ziehau KKASSERT(dn_sopt.dn_sopt_arg == NULL);
500879652a3SSepherosa Ziehau KKASSERT(dn_sopt.dn_sopt_arglen == 0);
501879652a3SSepherosa Ziehau return error;
502879652a3SSepherosa Ziehau }
503879652a3SSepherosa Ziehau
504e71a125fSAggelos Economopoulos soopt_from_kbuf(sopt, dn_sopt.dn_sopt_arg, dn_sopt.dn_sopt_arglen);
505879652a3SSepherosa Ziehau kfree(dn_sopt.dn_sopt_arg, M_TEMP);
506e71a125fSAggelos Economopoulos return 0;
507879652a3SSepherosa Ziehau }
508879652a3SSepherosa Ziehau
509879652a3SSepherosa Ziehau static int
ip_dn_sockopt_config(struct sockopt * sopt)510879652a3SSepherosa Ziehau ip_dn_sockopt_config(struct sockopt *sopt)
511879652a3SSepherosa Ziehau {
512879652a3SSepherosa Ziehau struct dn_ioc_pipe tmp_ioc_pipe;
513879652a3SSepherosa Ziehau struct dn_sopt dn_sopt;
514002c1265SMatthew Dillon struct netmsg_base smsg;
515879652a3SSepherosa Ziehau int error;
516879652a3SSepherosa Ziehau
517e71a125fSAggelos Economopoulos error = soopt_to_kbuf(sopt, &tmp_ioc_pipe, sizeof tmp_ioc_pipe,
518e71a125fSAggelos Economopoulos sizeof tmp_ioc_pipe);
519879652a3SSepherosa Ziehau if (error)
520879652a3SSepherosa Ziehau return error;
521879652a3SSepherosa Ziehau
522879652a3SSepherosa Ziehau bzero(&dn_sopt, sizeof(dn_sopt));
523879652a3SSepherosa Ziehau dn_sopt.dn_sopt_name = sopt->sopt_name;
524879652a3SSepherosa Ziehau dn_sopt.dn_sopt_arg = &tmp_ioc_pipe;
525879652a3SSepherosa Ziehau dn_sopt.dn_sopt_arglen = sizeof(tmp_ioc_pipe);
526879652a3SSepherosa Ziehau
52748e7b118SMatthew Dillon netmsg_init(&smsg, NULL, &curthread->td_msgport,
52848e7b118SMatthew Dillon 0, ip_dn_sockopt_dispatch);
529002c1265SMatthew Dillon smsg.lmsg.u.ms_resultp = &dn_sopt;
530ec7f7fc8SSepherosa Ziehau lwkt_domsg(netisr_cpuport(ip_dn_cpu), &smsg.lmsg, 0);
531879652a3SSepherosa Ziehau
532002c1265SMatthew Dillon return smsg.lmsg.ms_error;
533879652a3SSepherosa Ziehau }
534