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 * 34*879652a3SSepherosa Ziehau * $DragonFly: src/sys/net/dummynet/ip_dummynet_glue.c,v 1.4 2007/11/18 13:00:28 sephe Exp $ 3584a3e25aSSepherosa Ziehau */ 3684a3e25aSSepherosa Ziehau 3784a3e25aSSepherosa Ziehau #include <sys/param.h> 38329bf5d1SSepherosa Ziehau #include <sys/kernel.h> 3984a3e25aSSepherosa Ziehau #include <sys/mbuf.h> 4084a3e25aSSepherosa Ziehau #include <sys/msgport.h> 41*879652a3SSepherosa Ziehau #include <sys/socketvar.h> 42329bf5d1SSepherosa Ziehau #include <sys/sysctl.h> 4384a3e25aSSepherosa Ziehau 4484a3e25aSSepherosa Ziehau #include <net/if.h> 4584a3e25aSSepherosa Ziehau #include <net/if_var.h> 4684a3e25aSSepherosa Ziehau #include <net/route.h> 4784a3e25aSSepherosa Ziehau #include <net/ethernet.h> 4884a3e25aSSepherosa Ziehau #include <net/netisr.h> 4984a3e25aSSepherosa Ziehau #include <net/netmsg2.h> 5084a3e25aSSepherosa Ziehau 5184a3e25aSSepherosa Ziehau #include <netinet/in.h> 5284a3e25aSSepherosa Ziehau #include <netinet/in_var.h> 5384a3e25aSSepherosa Ziehau #include <netinet/ip.h> 5484a3e25aSSepherosa Ziehau #include <netinet/ip_var.h> 5584a3e25aSSepherosa Ziehau 5684a3e25aSSepherosa Ziehau #include <net/dummynet/ip_dummynet.h> 5784a3e25aSSepherosa Ziehau 5884a3e25aSSepherosa Ziehau static void ip_dn_ether_output(struct netmsg *); 5984a3e25aSSepherosa Ziehau static void ip_dn_ether_demux(struct netmsg *); 6084a3e25aSSepherosa Ziehau static void ip_dn_ip_input(struct netmsg *); 6184a3e25aSSepherosa Ziehau static void ip_dn_ip_output(struct netmsg *); 6284a3e25aSSepherosa Ziehau 63*879652a3SSepherosa Ziehau static void ip_dn_sockopt_dispatch(struct netmsg *); 6484a3e25aSSepherosa Ziehau static void ip_dn_freepkt_dispatch(struct netmsg *); 6584a3e25aSSepherosa Ziehau static void ip_dn_dispatch(struct netmsg *); 6684a3e25aSSepherosa Ziehau 6784a3e25aSSepherosa Ziehau static void ip_dn_freepkt(struct dn_pkt *); 6884a3e25aSSepherosa Ziehau 69*879652a3SSepherosa Ziehau static int ip_dn_sockopt_flush(struct sockopt *); 70*879652a3SSepherosa Ziehau static int ip_dn_sockopt_get(struct sockopt *); 71*879652a3SSepherosa Ziehau static int ip_dn_sockopt_config(struct sockopt *); 72*879652a3SSepherosa Ziehau 7384a3e25aSSepherosa Ziehau ip_dn_io_t *ip_dn_io_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 8384a3e25aSSepherosa Ziehau ip_dn_queue(struct mbuf *m) 8484a3e25aSSepherosa Ziehau { 8584a3e25aSSepherosa Ziehau struct netmsg_packet *nmp; 8684a3e25aSSepherosa Ziehau lwkt_port_t port; 8784a3e25aSSepherosa Ziehau 8884a3e25aSSepherosa Ziehau KASSERT(m->m_type != MT_TAG, ("mbuf contains old style tag!\n")); 89840665f6SSepherosa Ziehau M_ASSERTPKTHDR(m); 90840665f6SSepherosa Ziehau KASSERT(m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED, 91840665f6SSepherosa Ziehau ("mbuf is not tagged for dummynet!\n")); 9284a3e25aSSepherosa Ziehau 9384a3e25aSSepherosa Ziehau nmp = &m->m_hdr.mh_netmsg; 9484a3e25aSSepherosa Ziehau netmsg_init(&nmp->nm_netmsg, &netisr_apanic_rport, 0, 9584a3e25aSSepherosa Ziehau ip_dn_dispatch); 9684a3e25aSSepherosa Ziehau nmp->nm_packet = m; 9784a3e25aSSepherosa Ziehau 9884a3e25aSSepherosa Ziehau port = cpu_portfn(ip_dn_cpu); 9984a3e25aSSepherosa Ziehau lwkt_sendmsg(port, &nmp->nm_netmsg.nm_lmsg); 10084a3e25aSSepherosa Ziehau } 10184a3e25aSSepherosa Ziehau 10284a3e25aSSepherosa Ziehau void 10384a3e25aSSepherosa Ziehau ip_dn_packet_free(struct dn_pkt *pkt) 10484a3e25aSSepherosa Ziehau { 10584a3e25aSSepherosa Ziehau struct netmsg_packet *nmp; 10684a3e25aSSepherosa Ziehau lwkt_port_t port; 10784a3e25aSSepherosa Ziehau struct mbuf *m = pkt->dn_m; 10884a3e25aSSepherosa Ziehau 10984a3e25aSSepherosa Ziehau KASSERT(m->m_type != MT_TAG, ("mbuf contains old style tag!\n")); 110840665f6SSepherosa Ziehau M_ASSERTPKTHDR(m); 111840665f6SSepherosa Ziehau KASSERT(m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED, 112840665f6SSepherosa Ziehau ("mbuf is not tagged for dummynet!\n")); 11384a3e25aSSepherosa Ziehau 11484a3e25aSSepherosa Ziehau if (pkt->cpuid == mycpuid) { 11584a3e25aSSepherosa Ziehau ip_dn_freepkt(pkt); 11684a3e25aSSepherosa Ziehau return; 11784a3e25aSSepherosa Ziehau } 11884a3e25aSSepherosa Ziehau 11984a3e25aSSepherosa Ziehau nmp = &m->m_hdr.mh_netmsg; 12084a3e25aSSepherosa Ziehau netmsg_init(&nmp->nm_netmsg, &netisr_apanic_rport, 0, 12184a3e25aSSepherosa Ziehau ip_dn_freepkt_dispatch); 12284a3e25aSSepherosa Ziehau nmp->nm_packet = m; 12384a3e25aSSepherosa Ziehau 12484a3e25aSSepherosa Ziehau port = cpu_portfn(pkt->cpuid); 12584a3e25aSSepherosa Ziehau lwkt_sendmsg(port, &nmp->nm_netmsg.nm_lmsg); 12684a3e25aSSepherosa Ziehau } 12784a3e25aSSepherosa Ziehau 12884a3e25aSSepherosa Ziehau void 12984a3e25aSSepherosa Ziehau ip_dn_packet_redispatch(struct dn_pkt *pkt) 13084a3e25aSSepherosa Ziehau { 13184a3e25aSSepherosa Ziehau static const netisr_fn_t dispatches[DN_TO_MAX] = { 13284a3e25aSSepherosa Ziehau [DN_TO_IP_OUT] = ip_dn_ip_output, 13384a3e25aSSepherosa Ziehau [DN_TO_IP_IN] = ip_dn_ip_input, 13484a3e25aSSepherosa Ziehau [DN_TO_ETH_DEMUX] = ip_dn_ether_demux, 13584a3e25aSSepherosa Ziehau [DN_TO_ETH_OUT] = ip_dn_ether_output 13684a3e25aSSepherosa Ziehau }; 13784a3e25aSSepherosa Ziehau 13884a3e25aSSepherosa Ziehau struct netmsg_packet *nmp; 13984a3e25aSSepherosa Ziehau struct mbuf *m; 14084a3e25aSSepherosa Ziehau netisr_fn_t dispatch; 14184a3e25aSSepherosa Ziehau lwkt_port_t port; 14284a3e25aSSepherosa Ziehau int dir; 14384a3e25aSSepherosa Ziehau 14484a3e25aSSepherosa Ziehau dir = (pkt->dn_flags & DN_FLAGS_DIR_MASK); 14584a3e25aSSepherosa Ziehau KASSERT(dir < DN_TO_MAX, 14684a3e25aSSepherosa Ziehau ("unknown dummynet redispatch dir %d\n", dir)); 14784a3e25aSSepherosa Ziehau 14884a3e25aSSepherosa Ziehau dispatch = dispatches[dir]; 14984a3e25aSSepherosa Ziehau KASSERT(dispatch != NULL, 15084a3e25aSSepherosa Ziehau ("unsupported dummynet redispatch dir %d\n", dir)); 15184a3e25aSSepherosa Ziehau 15284a3e25aSSepherosa Ziehau m = pkt->dn_m; 15384a3e25aSSepherosa Ziehau KASSERT(m->m_type != MT_TAG, ("mbuf contains old style tag!\n")); 154840665f6SSepherosa Ziehau M_ASSERTPKTHDR(m); 155840665f6SSepherosa Ziehau KASSERT(m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED, 156840665f6SSepherosa Ziehau ("mbuf is not tagged for dummynet!\n")); 15784a3e25aSSepherosa Ziehau 15884a3e25aSSepherosa Ziehau nmp = &m->m_hdr.mh_netmsg; 15984a3e25aSSepherosa Ziehau netmsg_init(&nmp->nm_netmsg, &netisr_apanic_rport, 0, dispatch); 16084a3e25aSSepherosa Ziehau nmp->nm_packet = m; 16184a3e25aSSepherosa Ziehau 16284a3e25aSSepherosa Ziehau port = cpu_portfn(pkt->cpuid); 16384a3e25aSSepherosa Ziehau lwkt_sendmsg(port, &nmp->nm_netmsg.nm_lmsg); 16484a3e25aSSepherosa Ziehau } 16584a3e25aSSepherosa Ziehau 166*879652a3SSepherosa Ziehau int 167*879652a3SSepherosa Ziehau ip_dn_sockopt(struct sockopt *sopt) 168*879652a3SSepherosa Ziehau { 169*879652a3SSepherosa Ziehau int error = 0; 170*879652a3SSepherosa Ziehau 171*879652a3SSepherosa Ziehau /* Disallow sets in really-really secure mode. */ 172*879652a3SSepherosa Ziehau if (sopt->sopt_dir == SOPT_SET) { 173*879652a3SSepherosa Ziehau if (securelevel >= 3) 174*879652a3SSepherosa Ziehau return EPERM; 175*879652a3SSepherosa Ziehau } 176*879652a3SSepherosa Ziehau 177*879652a3SSepherosa Ziehau switch (sopt->sopt_name) { 178*879652a3SSepherosa Ziehau case IP_DUMMYNET_GET: 179*879652a3SSepherosa Ziehau error = ip_dn_sockopt_get(sopt); 180*879652a3SSepherosa Ziehau break; 181*879652a3SSepherosa Ziehau 182*879652a3SSepherosa Ziehau case IP_DUMMYNET_FLUSH: 183*879652a3SSepherosa Ziehau error = ip_dn_sockopt_flush(sopt); 184*879652a3SSepherosa Ziehau break; 185*879652a3SSepherosa Ziehau 186*879652a3SSepherosa Ziehau case IP_DUMMYNET_DEL: 187*879652a3SSepherosa Ziehau case IP_DUMMYNET_CONFIGURE: 188*879652a3SSepherosa Ziehau error = ip_dn_sockopt_config(sopt); 189*879652a3SSepherosa Ziehau break; 190*879652a3SSepherosa Ziehau 191*879652a3SSepherosa Ziehau default: 192*879652a3SSepherosa Ziehau kprintf("%s -- unknown option %d\n", __func__, sopt->sopt_name); 193*879652a3SSepherosa Ziehau error = EINVAL; 194*879652a3SSepherosa Ziehau break; 195*879652a3SSepherosa Ziehau } 196*879652a3SSepherosa Ziehau return error; 197*879652a3SSepherosa Ziehau } 198*879652a3SSepherosa Ziehau 19984a3e25aSSepherosa Ziehau static void 20084a3e25aSSepherosa Ziehau ip_dn_freepkt(struct dn_pkt *pkt) 20184a3e25aSSepherosa Ziehau { 20284a3e25aSSepherosa Ziehau struct rtentry *rt = pkt->ro.ro_rt; 20384a3e25aSSepherosa Ziehau 20484a3e25aSSepherosa Ziehau /* Unreference route entry */ 20584a3e25aSSepherosa Ziehau if (rt != NULL) { 20684a3e25aSSepherosa Ziehau if (rt->rt_refcnt <= 0) { /* XXX assert? */ 20784a3e25aSSepherosa Ziehau kprintf("-- warning, refcnt now %ld, decreasing\n", 20884a3e25aSSepherosa Ziehau rt->rt_refcnt); 20984a3e25aSSepherosa Ziehau } 21084a3e25aSSepherosa Ziehau RTFREE(rt); 21184a3e25aSSepherosa Ziehau } 21284a3e25aSSepherosa Ziehau 21384a3e25aSSepherosa Ziehau /* Unreference packet private data */ 21484a3e25aSSepherosa Ziehau if (pkt->dn_unref_priv) 21584a3e25aSSepherosa Ziehau pkt->dn_unref_priv(pkt->dn_priv); 21684a3e25aSSepherosa Ziehau 21784a3e25aSSepherosa Ziehau /* Free the parent mbuf, this will free 'pkt' as well */ 21884a3e25aSSepherosa Ziehau m_freem(pkt->dn_m); 21984a3e25aSSepherosa Ziehau } 22084a3e25aSSepherosa Ziehau 22184a3e25aSSepherosa Ziehau static void 22284a3e25aSSepherosa Ziehau ip_dn_freepkt_dispatch(struct netmsg *nmsg) 22384a3e25aSSepherosa Ziehau { 22484a3e25aSSepherosa Ziehau struct netmsg_packet *nmp; 22584a3e25aSSepherosa Ziehau struct mbuf *m; 22684a3e25aSSepherosa Ziehau struct m_tag *mtag; 22784a3e25aSSepherosa Ziehau struct dn_pkt *pkt; 22884a3e25aSSepherosa Ziehau 22984a3e25aSSepherosa Ziehau nmp = (struct netmsg_packet *)nmsg; 23084a3e25aSSepherosa Ziehau m = nmp->nm_packet; 231840665f6SSepherosa Ziehau M_ASSERTPKTHDR(m); 232840665f6SSepherosa Ziehau KASSERT(m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED, 233840665f6SSepherosa Ziehau ("mbuf is not tagged for dummynet!\n")); 23484a3e25aSSepherosa Ziehau 23584a3e25aSSepherosa Ziehau mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL); 236840665f6SSepherosa Ziehau KKASSERT(mtag != NULL); 23784a3e25aSSepherosa Ziehau 238840665f6SSepherosa Ziehau pkt = m_tag_data(mtag); 23984a3e25aSSepherosa Ziehau KASSERT(pkt->cpuid == mycpuid, 24084a3e25aSSepherosa Ziehau ("%s: dummynet packet was delivered to wrong cpu! " 24184a3e25aSSepherosa Ziehau "target cpuid %d, mycpuid %d\n", __func__, 24284a3e25aSSepherosa Ziehau pkt->cpuid, mycpuid)); 24384a3e25aSSepherosa Ziehau 24484a3e25aSSepherosa Ziehau ip_dn_freepkt(pkt); 24584a3e25aSSepherosa Ziehau } 24684a3e25aSSepherosa Ziehau 24784a3e25aSSepherosa Ziehau static void 24884a3e25aSSepherosa Ziehau ip_dn_dispatch(struct netmsg *nmsg) 24984a3e25aSSepherosa Ziehau { 25084a3e25aSSepherosa Ziehau struct netmsg_packet *nmp; 25184a3e25aSSepherosa Ziehau struct mbuf *m; 25284a3e25aSSepherosa Ziehau struct m_tag *mtag; 25384a3e25aSSepherosa Ziehau struct dn_pkt *pkt; 25484a3e25aSSepherosa Ziehau 25584a3e25aSSepherosa Ziehau KASSERT(ip_dn_cpu == mycpuid, 25684a3e25aSSepherosa Ziehau ("%s: dummynet packet was delivered to wrong cpu! " 25784a3e25aSSepherosa Ziehau "dummynet cpuid %d, mycpuid %d\n", __func__, 25884a3e25aSSepherosa Ziehau ip_dn_cpu, mycpuid)); 25984a3e25aSSepherosa Ziehau 26084a3e25aSSepherosa Ziehau nmp = (struct netmsg_packet *)nmsg; 26184a3e25aSSepherosa Ziehau m = nmp->nm_packet; 262840665f6SSepherosa Ziehau M_ASSERTPKTHDR(m); 263840665f6SSepherosa Ziehau KASSERT(m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED, 264840665f6SSepherosa Ziehau ("mbuf is not tagged for dummynet!\n")); 26584a3e25aSSepherosa Ziehau 26684a3e25aSSepherosa Ziehau if (DUMMYNET_LOADED) { 26784a3e25aSSepherosa Ziehau if (ip_dn_io_ptr(m) == 0) 26884a3e25aSSepherosa Ziehau return; 26984a3e25aSSepherosa Ziehau } 27084a3e25aSSepherosa Ziehau 27184a3e25aSSepherosa Ziehau /* 27284a3e25aSSepherosa Ziehau * ip_dn_io_ptr() failed or dummynet(4) is not loaded 27384a3e25aSSepherosa Ziehau */ 27484a3e25aSSepherosa Ziehau mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL); 275840665f6SSepherosa Ziehau KKASSERT(mtag != NULL); 276840665f6SSepherosa Ziehau 27784a3e25aSSepherosa Ziehau pkt = m_tag_data(mtag); 27884a3e25aSSepherosa Ziehau ip_dn_packet_free(pkt); 27984a3e25aSSepherosa Ziehau } 28084a3e25aSSepherosa Ziehau 28184a3e25aSSepherosa Ziehau static void 28284a3e25aSSepherosa Ziehau ip_dn_ip_output(struct netmsg *nmsg) 28384a3e25aSSepherosa Ziehau { 28484a3e25aSSepherosa Ziehau struct netmsg_packet *nmp; 28584a3e25aSSepherosa Ziehau struct mbuf *m; 28684a3e25aSSepherosa Ziehau struct m_tag *mtag; 28784a3e25aSSepherosa Ziehau struct dn_pkt *pkt; 28884a3e25aSSepherosa Ziehau struct rtentry *rt; 28984a3e25aSSepherosa Ziehau ip_dn_unref_priv_t unref_priv; 29084a3e25aSSepherosa Ziehau void *priv; 29184a3e25aSSepherosa Ziehau 29284a3e25aSSepherosa Ziehau nmp = (struct netmsg_packet *)nmsg; 29384a3e25aSSepherosa Ziehau m = nmp->nm_packet; 294840665f6SSepherosa Ziehau M_ASSERTPKTHDR(m); 295840665f6SSepherosa Ziehau KASSERT(m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED, 296840665f6SSepherosa Ziehau ("mbuf is not tagged for dummynet!\n")); 29784a3e25aSSepherosa Ziehau 29884a3e25aSSepherosa Ziehau mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL); 29984a3e25aSSepherosa Ziehau KKASSERT(mtag != NULL); 30084a3e25aSSepherosa Ziehau 30184a3e25aSSepherosa Ziehau pkt = m_tag_data(mtag); 30284a3e25aSSepherosa Ziehau KASSERT(pkt->cpuid == mycpuid, 30384a3e25aSSepherosa Ziehau ("%s: dummynet packet was delivered to wrong cpu! " 30484a3e25aSSepherosa Ziehau "target cpuid %d, mycpuid %d\n", __func__, 30584a3e25aSSepherosa Ziehau pkt->cpuid, mycpuid)); 30684a3e25aSSepherosa Ziehau KASSERT((pkt->dn_flags & DN_FLAGS_DIR_MASK) == DN_TO_IP_OUT, 30784a3e25aSSepherosa Ziehau ("wrong direction %d, should be %d\n", 30884a3e25aSSepherosa Ziehau (pkt->dn_flags & DN_FLAGS_DIR_MASK), DN_TO_IP_OUT)); 30984a3e25aSSepherosa Ziehau 31084a3e25aSSepherosa Ziehau priv = pkt->dn_priv; 31184a3e25aSSepherosa Ziehau unref_priv = pkt->dn_unref_priv; 31284a3e25aSSepherosa Ziehau rt = pkt->ro.ro_rt; 31384a3e25aSSepherosa Ziehau 31484a3e25aSSepherosa Ziehau if (rt != NULL && !(rt->rt_flags & RTF_UP)) { 31584a3e25aSSepherosa Ziehau /* 31684a3e25aSSepherosa Ziehau * Recorded rtentry is gone, when the packet 31784a3e25aSSepherosa Ziehau * was on delay line. 31884a3e25aSSepherosa Ziehau */ 31984a3e25aSSepherosa Ziehau ip_dn_freepkt(pkt); 32084a3e25aSSepherosa Ziehau return; 32184a3e25aSSepherosa Ziehau } 32284a3e25aSSepherosa Ziehau 32384a3e25aSSepherosa Ziehau ip_output(pkt->dn_m, NULL, NULL, 0, NULL, NULL); 32484a3e25aSSepherosa Ziehau 32584a3e25aSSepherosa Ziehau if (rt != NULL) { 32684a3e25aSSepherosa Ziehau if (rt->rt_refcnt <= 0) { /* XXX assert? */ 32784a3e25aSSepherosa Ziehau kprintf("-- warning, refcnt now %ld, decreasing\n", 32884a3e25aSSepherosa Ziehau rt->rt_refcnt); 32984a3e25aSSepherosa Ziehau } 33084a3e25aSSepherosa Ziehau RTFREE(rt); 33184a3e25aSSepherosa Ziehau } 33284a3e25aSSepherosa Ziehau if (unref_priv) 33384a3e25aSSepherosa Ziehau unref_priv(priv); 33484a3e25aSSepherosa Ziehau } 33584a3e25aSSepherosa Ziehau 33684a3e25aSSepherosa Ziehau static void 33784a3e25aSSepherosa Ziehau ip_dn_ip_input(struct netmsg *nmsg) 33884a3e25aSSepherosa Ziehau { 33984a3e25aSSepherosa Ziehau struct netmsg_packet *nmp; 34084a3e25aSSepherosa Ziehau struct mbuf *m; 34184a3e25aSSepherosa Ziehau struct m_tag *mtag; 34284a3e25aSSepherosa Ziehau struct dn_pkt *pkt; 34384a3e25aSSepherosa Ziehau ip_dn_unref_priv_t unref_priv; 34484a3e25aSSepherosa Ziehau void *priv; 34584a3e25aSSepherosa Ziehau 34684a3e25aSSepherosa Ziehau nmp = (struct netmsg_packet *)nmsg; 34784a3e25aSSepherosa Ziehau m = nmp->nm_packet; 348840665f6SSepherosa Ziehau M_ASSERTPKTHDR(m); 349840665f6SSepherosa Ziehau KASSERT(m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED, 350840665f6SSepherosa Ziehau ("mbuf is not tagged for dummynet!\n")); 35184a3e25aSSepherosa Ziehau 35284a3e25aSSepherosa Ziehau mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL); 35384a3e25aSSepherosa Ziehau KKASSERT(mtag != NULL); 35484a3e25aSSepherosa Ziehau 35584a3e25aSSepherosa Ziehau pkt = m_tag_data(mtag); 35684a3e25aSSepherosa Ziehau KASSERT(pkt->cpuid == mycpuid, 35784a3e25aSSepherosa Ziehau ("%s: dummynet packet was delivered to wrong cpu! " 35884a3e25aSSepherosa Ziehau "target cpuid %d, mycpuid %d\n", __func__, 35984a3e25aSSepherosa Ziehau pkt->cpuid, mycpuid)); 36084a3e25aSSepherosa Ziehau KASSERT(pkt->ro.ro_rt == NULL, 36184a3e25aSSepherosa Ziehau ("route entry is not NULL for ip_input\n")); 36284a3e25aSSepherosa Ziehau KASSERT((pkt->dn_flags & DN_FLAGS_DIR_MASK) == DN_TO_IP_IN, 36384a3e25aSSepherosa Ziehau ("wrong direction %d, should be %d\n", 36484a3e25aSSepherosa Ziehau (pkt->dn_flags & DN_FLAGS_DIR_MASK), DN_TO_IP_IN)); 36584a3e25aSSepherosa Ziehau 36684a3e25aSSepherosa Ziehau priv = pkt->dn_priv; 36784a3e25aSSepherosa Ziehau unref_priv = pkt->dn_unref_priv; 36884a3e25aSSepherosa Ziehau 36984a3e25aSSepherosa Ziehau ip_input(m); 37084a3e25aSSepherosa Ziehau 37184a3e25aSSepherosa Ziehau if (unref_priv) 37284a3e25aSSepherosa Ziehau unref_priv(priv); 37384a3e25aSSepherosa Ziehau } 37484a3e25aSSepherosa Ziehau 37584a3e25aSSepherosa Ziehau static void 37684a3e25aSSepherosa Ziehau ip_dn_ether_demux(struct netmsg *nmsg) 37784a3e25aSSepherosa Ziehau { 37884a3e25aSSepherosa Ziehau struct netmsg_packet *nmp; 37984a3e25aSSepherosa Ziehau struct mbuf *m; 38084a3e25aSSepherosa Ziehau struct m_tag *mtag; 38184a3e25aSSepherosa Ziehau struct dn_pkt *pkt; 38284a3e25aSSepherosa Ziehau struct ether_header *eh; 38384a3e25aSSepherosa Ziehau ip_dn_unref_priv_t unref_priv; 38484a3e25aSSepherosa Ziehau void *priv; 38584a3e25aSSepherosa Ziehau 38684a3e25aSSepherosa Ziehau nmp = (struct netmsg_packet *)nmsg; 38784a3e25aSSepherosa Ziehau m = nmp->nm_packet; 388840665f6SSepherosa Ziehau M_ASSERTPKTHDR(m); 389840665f6SSepherosa Ziehau KASSERT(m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED, 390840665f6SSepherosa Ziehau ("mbuf is not tagged for dummynet!\n")); 39184a3e25aSSepherosa Ziehau 39284a3e25aSSepherosa Ziehau mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL); 39384a3e25aSSepherosa Ziehau KKASSERT(mtag != NULL); 39484a3e25aSSepherosa Ziehau 39584a3e25aSSepherosa Ziehau pkt = m_tag_data(mtag); 39684a3e25aSSepherosa Ziehau KASSERT(pkt->cpuid == mycpuid, 39784a3e25aSSepherosa Ziehau ("%s: dummynet packet was delivered to wrong cpu! " 39884a3e25aSSepherosa Ziehau "target cpuid %d, mycpuid %d\n", __func__, 39984a3e25aSSepherosa Ziehau pkt->cpuid, mycpuid)); 40084a3e25aSSepherosa Ziehau KASSERT(pkt->ro.ro_rt == NULL, 40184a3e25aSSepherosa Ziehau ("route entry is not NULL for ether_demux\n")); 40284a3e25aSSepherosa Ziehau KASSERT((pkt->dn_flags & DN_FLAGS_DIR_MASK) == DN_TO_ETH_DEMUX, 40384a3e25aSSepherosa Ziehau ("wrong direction %d, should be %d\n", 40484a3e25aSSepherosa Ziehau (pkt->dn_flags & DN_FLAGS_DIR_MASK), DN_TO_ETH_DEMUX)); 40584a3e25aSSepherosa Ziehau 40684a3e25aSSepherosa Ziehau priv = pkt->dn_priv; 40784a3e25aSSepherosa Ziehau unref_priv = pkt->dn_unref_priv; 40884a3e25aSSepherosa Ziehau 40984a3e25aSSepherosa Ziehau if (m->m_len < ETHER_HDR_LEN && 41084a3e25aSSepherosa Ziehau (m = m_pullup(m, ETHER_HDR_LEN)) == NULL) { 41184a3e25aSSepherosa Ziehau kprintf("%s: pullup fail, dropping pkt\n", __func__); 41284a3e25aSSepherosa Ziehau goto back; 41384a3e25aSSepherosa Ziehau } 41484a3e25aSSepherosa Ziehau 41584a3e25aSSepherosa Ziehau /* 41684a3e25aSSepherosa Ziehau * Same as ether_input, make eh be a pointer into the mbuf 41784a3e25aSSepherosa Ziehau */ 41884a3e25aSSepherosa Ziehau eh = mtod(m, struct ether_header *); 41984a3e25aSSepherosa Ziehau m_adj(m, ETHER_HDR_LEN); 42084a3e25aSSepherosa Ziehau ether_demux(NULL, eh, m); 42184a3e25aSSepherosa Ziehau back: 42284a3e25aSSepherosa Ziehau if (unref_priv) 42384a3e25aSSepherosa Ziehau unref_priv(priv); 42484a3e25aSSepherosa Ziehau } 42584a3e25aSSepherosa Ziehau 42684a3e25aSSepherosa Ziehau static void 42784a3e25aSSepherosa Ziehau ip_dn_ether_output(struct netmsg *nmsg) 42884a3e25aSSepherosa Ziehau { 42984a3e25aSSepherosa Ziehau struct netmsg_packet *nmp; 43084a3e25aSSepherosa Ziehau struct mbuf *m; 43184a3e25aSSepherosa Ziehau struct m_tag *mtag; 43284a3e25aSSepherosa Ziehau struct dn_pkt *pkt; 43384a3e25aSSepherosa Ziehau ip_dn_unref_priv_t unref_priv; 43484a3e25aSSepherosa Ziehau void *priv; 43584a3e25aSSepherosa Ziehau 43684a3e25aSSepherosa Ziehau nmp = (struct netmsg_packet *)nmsg; 43784a3e25aSSepherosa Ziehau m = nmp->nm_packet; 438840665f6SSepherosa Ziehau M_ASSERTPKTHDR(m); 439840665f6SSepherosa Ziehau KASSERT(m->m_pkthdr.fw_flags & DUMMYNET_MBUF_TAGGED, 440840665f6SSepherosa Ziehau ("mbuf is not tagged for dummynet!\n")); 44184a3e25aSSepherosa Ziehau 44284a3e25aSSepherosa Ziehau mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL); 44384a3e25aSSepherosa Ziehau KKASSERT(mtag != NULL); 44484a3e25aSSepherosa Ziehau 44584a3e25aSSepherosa Ziehau pkt = m_tag_data(mtag); 44684a3e25aSSepherosa Ziehau KASSERT(pkt->cpuid == mycpuid, 44784a3e25aSSepherosa Ziehau ("%s: dummynet packet was delivered to wrong cpu! " 44884a3e25aSSepherosa Ziehau "target cpuid %d, mycpuid %d\n", __func__, 44984a3e25aSSepherosa Ziehau pkt->cpuid, mycpuid)); 45084a3e25aSSepherosa Ziehau KASSERT(pkt->ro.ro_rt == NULL, 45184a3e25aSSepherosa Ziehau ("route entry is not NULL for ether_output_frame\n")); 45284a3e25aSSepherosa Ziehau KASSERT((pkt->dn_flags & DN_FLAGS_DIR_MASK) == DN_TO_ETH_OUT, 45384a3e25aSSepherosa Ziehau ("wrong direction %d, should be %d\n", 45484a3e25aSSepherosa Ziehau (pkt->dn_flags & DN_FLAGS_DIR_MASK), DN_TO_ETH_OUT)); 45584a3e25aSSepherosa Ziehau 45684a3e25aSSepherosa Ziehau priv = pkt->dn_priv; 45784a3e25aSSepherosa Ziehau unref_priv = pkt->dn_unref_priv; 45884a3e25aSSepherosa Ziehau 45984a3e25aSSepherosa Ziehau ether_output_frame(pkt->ifp, m); 46084a3e25aSSepherosa Ziehau 46184a3e25aSSepherosa Ziehau if (unref_priv) 46284a3e25aSSepherosa Ziehau unref_priv(priv); 46384a3e25aSSepherosa Ziehau } 464*879652a3SSepherosa Ziehau 465*879652a3SSepherosa Ziehau static void 466*879652a3SSepherosa Ziehau ip_dn_sockopt_dispatch(struct netmsg *nmsg) 467*879652a3SSepherosa Ziehau { 468*879652a3SSepherosa Ziehau lwkt_msg *msg = &nmsg->nm_lmsg; 469*879652a3SSepherosa Ziehau struct dn_sopt *dn_sopt = msg->u.ms_resultp; 470*879652a3SSepherosa Ziehau int error; 471*879652a3SSepherosa Ziehau 472*879652a3SSepherosa Ziehau KASSERT(ip_dn_cpu == mycpuid, 473*879652a3SSepherosa Ziehau ("%s: dummynet sockopt is done on wrong cpu! " 474*879652a3SSepherosa Ziehau "dummynet cpuid %d, mycpuid %d\n", __func__, 475*879652a3SSepherosa Ziehau ip_dn_cpu, mycpuid)); 476*879652a3SSepherosa Ziehau 477*879652a3SSepherosa Ziehau if (DUMMYNET_LOADED) 478*879652a3SSepherosa Ziehau error = ip_dn_ctl_ptr(dn_sopt); 479*879652a3SSepherosa Ziehau else 480*879652a3SSepherosa Ziehau error = ENOPROTOOPT; 481*879652a3SSepherosa Ziehau lwkt_replymsg(msg, error); 482*879652a3SSepherosa Ziehau } 483*879652a3SSepherosa Ziehau 484*879652a3SSepherosa Ziehau static int 485*879652a3SSepherosa Ziehau ip_dn_sockopt_flush(struct sockopt *sopt) 486*879652a3SSepherosa Ziehau { 487*879652a3SSepherosa Ziehau struct dn_sopt dn_sopt; 488*879652a3SSepherosa Ziehau struct netmsg smsg; 489*879652a3SSepherosa Ziehau 490*879652a3SSepherosa Ziehau bzero(&dn_sopt, sizeof(dn_sopt)); 491*879652a3SSepherosa Ziehau dn_sopt.dn_sopt_name = sopt->sopt_name; 492*879652a3SSepherosa Ziehau 493*879652a3SSepherosa Ziehau netmsg_init(&smsg, &curthread->td_msgport, 0, ip_dn_sockopt_dispatch); 494*879652a3SSepherosa Ziehau smsg.nm_lmsg.u.ms_resultp = &dn_sopt; 495*879652a3SSepherosa Ziehau lwkt_domsg(cpu_portfn(ip_dn_cpu), &smsg.nm_lmsg, 0); 496*879652a3SSepherosa Ziehau 497*879652a3SSepherosa Ziehau return smsg.nm_lmsg.ms_error; 498*879652a3SSepherosa Ziehau } 499*879652a3SSepherosa Ziehau 500*879652a3SSepherosa Ziehau static int 501*879652a3SSepherosa Ziehau ip_dn_sockopt_get(struct sockopt *sopt) 502*879652a3SSepherosa Ziehau { 503*879652a3SSepherosa Ziehau struct dn_sopt dn_sopt; 504*879652a3SSepherosa Ziehau struct netmsg smsg; 505*879652a3SSepherosa Ziehau int error; 506*879652a3SSepherosa Ziehau 507*879652a3SSepherosa Ziehau bzero(&dn_sopt, sizeof(dn_sopt)); 508*879652a3SSepherosa Ziehau dn_sopt.dn_sopt_name = sopt->sopt_name; 509*879652a3SSepherosa Ziehau 510*879652a3SSepherosa Ziehau netmsg_init(&smsg, &curthread->td_msgport, 0, ip_dn_sockopt_dispatch); 511*879652a3SSepherosa Ziehau smsg.nm_lmsg.u.ms_resultp = &dn_sopt; 512*879652a3SSepherosa Ziehau lwkt_domsg(cpu_portfn(ip_dn_cpu), &smsg.nm_lmsg, 0); 513*879652a3SSepherosa Ziehau 514*879652a3SSepherosa Ziehau error = smsg.nm_lmsg.ms_error; 515*879652a3SSepherosa Ziehau if (error) { 516*879652a3SSepherosa Ziehau KKASSERT(dn_sopt.dn_sopt_arg == NULL); 517*879652a3SSepherosa Ziehau KKASSERT(dn_sopt.dn_sopt_arglen == 0); 518*879652a3SSepherosa Ziehau return error; 519*879652a3SSepherosa Ziehau } 520*879652a3SSepherosa Ziehau 521*879652a3SSepherosa Ziehau error = sooptcopyout(sopt, dn_sopt.dn_sopt_arg, dn_sopt.dn_sopt_arglen); 522*879652a3SSepherosa Ziehau kfree(dn_sopt.dn_sopt_arg, M_TEMP); 523*879652a3SSepherosa Ziehau return error; 524*879652a3SSepherosa Ziehau } 525*879652a3SSepherosa Ziehau 526*879652a3SSepherosa Ziehau static int 527*879652a3SSepherosa Ziehau ip_dn_sockopt_config(struct sockopt *sopt) 528*879652a3SSepherosa Ziehau { 529*879652a3SSepherosa Ziehau struct dn_ioc_pipe tmp_ioc_pipe; 530*879652a3SSepherosa Ziehau struct dn_sopt dn_sopt; 531*879652a3SSepherosa Ziehau struct netmsg smsg; 532*879652a3SSepherosa Ziehau int error; 533*879652a3SSepherosa Ziehau 534*879652a3SSepherosa Ziehau error = sooptcopyin(sopt, &tmp_ioc_pipe, sizeof(tmp_ioc_pipe), 535*879652a3SSepherosa Ziehau sizeof(tmp_ioc_pipe)); 536*879652a3SSepherosa Ziehau if (error) 537*879652a3SSepherosa Ziehau return error; 538*879652a3SSepherosa Ziehau 539*879652a3SSepherosa Ziehau bzero(&dn_sopt, sizeof(dn_sopt)); 540*879652a3SSepherosa Ziehau dn_sopt.dn_sopt_name = sopt->sopt_name; 541*879652a3SSepherosa Ziehau dn_sopt.dn_sopt_arg = &tmp_ioc_pipe; 542*879652a3SSepherosa Ziehau dn_sopt.dn_sopt_arglen = sizeof(tmp_ioc_pipe); 543*879652a3SSepherosa Ziehau 544*879652a3SSepherosa Ziehau netmsg_init(&smsg, &curthread->td_msgport, 0, ip_dn_sockopt_dispatch); 545*879652a3SSepherosa Ziehau smsg.nm_lmsg.u.ms_resultp = &dn_sopt; 546*879652a3SSepherosa Ziehau lwkt_domsg(cpu_portfn(ip_dn_cpu), &smsg.nm_lmsg, 0); 547*879652a3SSepherosa Ziehau 548*879652a3SSepherosa Ziehau return smsg.nm_lmsg.ms_error; 549*879652a3SSepherosa Ziehau } 550