2 /**************************************************************************
4 Copyright (c) 2007, Chelsio Inc.
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
10 1. Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
13 2. Neither the name of the Chelsio Corporation nor the names of its
14 contributors may be used to endorse or promote products derived from
15 this software without specific prior written permission.
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 POSSIBILITY OF SUCH DAMAGE.
29 ***************************************************************************/
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
38 #include <sys/module.h>
39 #include <sys/queue.h>
43 #include <sys/socket.h>
44 #include <sys/sockio.h>
47 #include <net/ethernet.h>
49 #include <net/route.h>
56 #include <cxgb_include.h>
58 #include <dev/cxgb/cxgb_include.h>
63 static struct mtx offload_db_lock;
64 static TAILQ_HEAD(, toedev) offload_dev_list;
65 static TAILQ_HEAD(, tom_info) offload_module_list;
68 * Returns the entry in the given table with the given offload id, or NULL
69 * if the id is not found.
71 static const struct offload_id *
72 id_find(unsigned int id, const struct offload_id *table)
74 for ( ; table->id; ++table)
81 * Returns true if an offload device is presently attached to an offload module.
84 is_attached(const struct toedev *dev)
86 return dev->tod_offload_mod != NULL;
90 * Try to attach a new offload device to an existing TCP offload module that
91 * can handle the device's offload id. Returns 0 if it succeeds.
93 * Must be called with the offload_db_lock held.
96 offload_attach(struct toedev *dev)
100 TAILQ_FOREACH(t, &offload_module_list, entry) {
101 const struct offload_id *entry;
103 entry = id_find(dev->tod_ttid, t->ti_id_table);
104 if (entry && t->ti_attach(dev, entry) == 0) {
105 dev->tod_offload_mod = t;
109 return (ENOPROTOOPT);
113 * register_tom - register a TCP Offload Module (TOM)
114 * @t: the offload module to register
116 * Register a TCP Offload Module (TOM).
119 register_tom(struct tom_info *t)
121 mtx_lock(&offload_db_lock);
122 TAILQ_INSERT_HEAD(&offload_module_list, t, entry);
123 mtx_unlock(&offload_db_lock);
128 * unregister_tom - unregister a TCP Offload Module (TOM)
129 * @t: the offload module to register
131 * Unregister a TCP Offload Module (TOM). Note that this does not affect any
132 * TOE devices to which the TOM is already attached.
135 unregister_tom(struct tom_info *t)
137 mtx_lock(&offload_db_lock);
138 TAILQ_REMOVE(&offload_module_list, t, entry);
139 mtx_unlock(&offload_db_lock);
144 * Find an offload device by name. Must be called with offload_db_lock held.
146 static struct toedev *
147 __find_offload_dev_by_name(const char *name)
151 TAILQ_FOREACH(dev, &offload_dev_list, entry) {
152 if (!strncmp(dev->tod_name, name, TOENAMSIZ))
159 * Returns true if an offload device is already registered.
160 * Must be called with the offload_db_lock held.
163 is_registered(const struct toedev *dev)
167 TAILQ_FOREACH(d, &offload_dev_list, entry) {
175 * Finalize the name of an offload device by assigning values to any format
176 * strings in its name.
179 assign_name(struct toedev *dev, const char *name, int limit)
183 for (i = 0; i < limit; ++i) {
186 if (snprintf(s, sizeof(s), name, i) >= sizeof(s))
187 return -1; /* name too long */
188 if (!__find_offload_dev_by_name(s)) {
189 strcpy(dev->tod_name, s);
197 * register_toedev - register a TOE device
199 * @name: a name template for the device
201 * Register a TOE device and try to attach an appropriate TCP offload module
202 * to it. @name is a template that may contain at most one %d format
206 register_toedev(struct toedev *dev, const char *name)
212 * Validate the name template. Only one %d allowed and name must be
213 * a valid filename so it can appear in sysfs.
215 if (!name || !*name || !strcmp(name, ".") || !strcmp(name, "..") ||
219 p = strchr(name, '%');
220 if (p && (p[1] != 'd' || strchr(p + 2, '%')))
223 mtx_lock(&offload_db_lock);
224 if (is_registered(dev)) { /* device already registered */
229 if ((ret = assign_name(dev, name, 32)) != 0)
232 dev->tod_offload_mod = NULL;
233 TAILQ_INSERT_TAIL(&offload_dev_list, dev, entry);
235 mtx_unlock(&offload_db_lock);
240 * unregister_toedev - unregister a TOE device
243 * Unregister a TOE device. The device must not be attached to an offload
247 unregister_toedev(struct toedev *dev)
251 mtx_lock(&offload_db_lock);
252 if (!is_registered(dev)) {
256 if (is_attached(dev)) {
260 TAILQ_REMOVE(&offload_dev_list, dev, entry);
262 mtx_unlock(&offload_db_lock);
267 * activate_offload - activate an offload device
270 * Activate an offload device by locating an appropriate registered offload
271 * module. If no module is found the operation fails and may be retried at
275 activate_offload(struct toedev *dev)
279 mtx_lock(&offload_db_lock);
280 if (!is_registered(dev))
282 else if (!is_attached(dev))
283 ret = offload_attach(dev);
284 mtx_unlock(&offload_db_lock);
289 * toe_send - send a packet to a TOE device
293 * Sends an mbuf to a TOE driver after dealing with any active network taps.
296 toe_send(struct toedev *dev, struct mbuf *m)
300 critical_enter(); /* XXX neccessary? */
301 r = dev->tod_send(dev, m);
304 BPF_MTAP(dev->tod_lldev, m);
309 * toe_receive_mbuf - process n received TOE packets
310 * @dev: the toe device
311 * @m: an array of offload packets
312 * @n: the number of offload packets
314 * Process an array of ingress offload packets. Each packet is forwarded
315 * to any active network taps and then passed to the toe device's receive
316 * method. We optimize passing packets to the receive method by passing
317 * it the whole array at once except when there are active taps.
320 toe_receive_mbuf(struct toedev *dev, struct mbuf **m, int n)
322 if (__predict_true(!bpf_peers_present(dev->tod_lldev->if_bpf)))
323 return dev->tod_recv(dev, m, n);
325 for ( ; n; n--, m++) {
326 m[0]->m_pkthdr.rcvif = dev->tod_lldev;
327 BPF_MTAP(dev->tod_lldev, m[0]);
328 dev->tod_recv(dev, m, 1);
334 ifnet_is_offload(const struct ifnet *ifp)
336 return (ifp->if_flags & IFCAP_TOE);
340 toe_arp_update(struct rtentry *rt)
342 struct ifnet *ifp = rt->rt_ifp;
344 if (ifp && ifnet_is_offload(ifp)) {
345 struct toedev *tdev = TOEDEV(ifp);
347 if (tdev && tdev->tod_arp_update)
348 tdev->tod_arp_update(tdev, rt);
353 * offload_get_phys_egress - find the physical egress device
354 * @root_dev: the root device anchoring the search
355 * @so: the socket used to determine egress port in bonding mode
356 * @context: in bonding mode, indicates a connection set up or failover
358 * Given a root network device it returns the physical egress device that is a
359 * descendant of the root device. The root device may be either a physical
360 * device, in which case it is the device returned, or a virtual device, such
361 * as a VLAN or bonding device. In case of a bonding device the search
362 * considers the decisions of the bonding device given its mode to locate the
363 * correct egress device.
366 offload_get_phys_egress(struct ifnet *root_dev, struct socket *so, int context)
370 while (root_dev && ifnet_is_offload(root_dev)) {
371 if (root_dev->tod_priv_flags & IFF_802_1Q_VLAN)
372 root_dev = VLAN_DEV_INFO(root_dev)->real_dev;
373 else if (root_dev->tod_flags & IFF_MASTER)
374 root_dev = toe_bond_get_slave(root_dev, sk, context);
383 toecore_load(module_t mod, int cmd, void *arg)
389 mtx_init(&offload_db_lock, "toedev lock", NULL, MTX_DEF);
390 TAILQ_INIT(&offload_dev_list);
391 TAILQ_INIT(&offload_module_list);
396 mtx_lock(&offload_db_lock);
397 if (!TAILQ_EMPTY(&offload_dev_list) ||
398 !TAILQ_EMPTY(&offload_module_list)) {
400 mtx_unlock(&offload_db_lock);
403 mtx_unlock(&offload_db_lock);
404 mtx_destroy(&offload_db_lock);
417 static moduledata_t mod_data= {
423 MODULE_VERSION(toecore, 1);
424 DECLARE_MODULE(toecore, mod_data, SI_SUB_EXEC, SI_ORDER_ANY);