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>
55 #include <cxgb_include.h>
56 #include <ulp/toecore/cxgb_toedev.h>
58 static struct mtx offload_db_lock;
59 static TAILQ_HEAD(, toedev) offload_dev_list;
60 static TAILQ_HEAD(, tom_info) offload_module_list;
63 * Returns the entry in the given table with the given offload id, or NULL
64 * if the id is not found.
66 static const struct offload_id *
67 id_find(unsigned int id, const struct offload_id *table)
69 for ( ; table->id; ++table)
76 * Returns true if an offload device is presently attached to an offload module.
79 is_attached(const struct toedev *dev)
81 return dev->tod_offload_mod != NULL;
85 * Try to attach a new offload device to an existing TCP offload module that
86 * can handle the device's offload id. Returns 0 if it succeeds.
88 * Must be called with the offload_db_lock held.
91 offload_attach(struct toedev *dev)
95 TAILQ_FOREACH(t, &offload_module_list, entry) {
96 const struct offload_id *entry;
98 entry = id_find(dev->tod_ttid, t->ti_id_table);
99 if (entry && t->ti_attach(dev, entry) == 0) {
100 dev->tod_offload_mod = t;
104 return (ENOPROTOOPT);
108 * register_tom - register a TCP Offload Module (TOM)
109 * @t: the offload module to register
111 * Register a TCP Offload Module (TOM).
114 register_tom(struct tom_info *t)
116 mtx_lock(&offload_db_lock);
117 toedev_registration_count++;
118 TAILQ_INSERT_HEAD(&offload_module_list, t, entry);
119 mtx_unlock(&offload_db_lock);
124 * unregister_tom - unregister a TCP Offload Module (TOM)
125 * @t: the offload module to register
127 * Unregister a TCP Offload Module (TOM). Note that this does not affect any
128 * TOE devices to which the TOM is already attached.
131 unregister_tom(struct tom_info *t)
133 mtx_lock(&offload_db_lock);
134 TAILQ_REMOVE(&offload_module_list, t, entry);
135 mtx_unlock(&offload_db_lock);
140 * Find an offload device by name. Must be called with offload_db_lock held.
142 static struct toedev *
143 __find_offload_dev_by_name(const char *name)
147 TAILQ_FOREACH(dev, &offload_dev_list, entry) {
148 if (!strncmp(dev->tod_name, name, TOENAMSIZ))
155 * Returns true if an offload device is already registered.
156 * Must be called with the offload_db_lock held.
159 is_registered(const struct toedev *dev)
163 TAILQ_FOREACH(d, &offload_dev_list, entry) {
171 * Finalize the name of an offload device by assigning values to any format
172 * strings in its name.
175 assign_name(struct toedev *dev, const char *name, int limit)
179 for (i = 0; i < limit; ++i) {
182 if (snprintf(s, sizeof(s), name, i) >= sizeof(s))
183 return -1; /* name too long */
184 if (!__find_offload_dev_by_name(s)) {
185 strcpy(dev->tod_name, s);
193 * register_toedev - register a TOE device
195 * @name: a name template for the device
197 * Register a TOE device and try to attach an appropriate TCP offload module
198 * to it. @name is a template that may contain at most one %d format
202 register_toedev(struct toedev *dev, const char *name)
208 * Validate the name template. Only one %d allowed and name must be
209 * a valid filename so it can appear in sysfs.
211 if (!name || !*name || !strcmp(name, ".") || !strcmp(name, "..") ||
215 p = strchr(name, '%');
216 if (p && (p[1] != 'd' || strchr(p + 2, '%')))
219 mtx_lock(&offload_db_lock);
220 if (is_registered(dev)) { /* device already registered */
225 if ((ret = assign_name(dev, name, 32)) != 0)
228 dev->tod_offload_mod = NULL;
229 TAILQ_INSERT_TAIL(&offload_dev_list, dev, entry);
231 mtx_unlock(&offload_db_lock);
236 * unregister_toedev - unregister a TOE device
239 * Unregister a TOE device. The device must not be attached to an offload
243 unregister_toedev(struct toedev *dev)
247 mtx_lock(&offload_db_lock);
248 if (!is_registered(dev)) {
252 if (is_attached(dev)) {
256 TAILQ_REMOVE(&offload_dev_list, dev, entry);
258 mtx_unlock(&offload_db_lock);
263 * activate_offload - activate an offload device
266 * Activate an offload device by locating an appropriate registered offload
267 * module. If no module is found the operation fails and may be retried at
271 activate_offload(struct toedev *dev)
275 mtx_lock(&offload_db_lock);
276 if (!is_registered(dev))
278 else if (!is_attached(dev))
279 ret = offload_attach(dev);
280 mtx_unlock(&offload_db_lock);
285 * toe_send - send a packet to a TOE device
289 * Sends an mbuf to a TOE driver after dealing with any active network taps.
292 toe_send(struct toedev *dev, struct mbuf *m)
296 critical_enter(); /* XXX neccessary? */
297 r = dev->tod_send(dev, m);
300 BPF_MTAP(dev->tod_lldev, m);
305 * toe_receive_mbuf - process n received TOE packets
306 * @dev: the toe device
307 * @m: an array of offload packets
308 * @n: the number of offload packets
310 * Process an array of ingress offload packets. Each packet is forwarded
311 * to any active network taps and then passed to the toe device's receive
312 * method. We optimize passing packets to the receive method by passing
313 * it the whole array at once except when there are active taps.
316 toe_receive_mbuf(struct toedev *dev, struct mbuf **m, int n)
318 if (__predict_true(!bpf_peers_present(dev->tod_lldev->if_bpf)))
319 return dev->tod_recv(dev, m, n);
321 for ( ; n; n--, m++) {
322 m[0]->m_pkthdr.rcvif = dev->tod_lldev;
323 BPF_MTAP(dev->tod_lldev, m[0]);
324 dev->tod_recv(dev, m, 1);
330 ifnet_is_offload(const struct ifnet *ifp)
332 return (ifp->if_flags & IFCAP_TOE);
336 toe_arp_update(struct rtentry *rt)
338 struct ifnet *ifp = rt->rt_ifp;
340 if (ifp && ifnet_is_offload(ifp)) {
341 struct toedev *tdev = TOEDEV(ifp);
343 if (tdev && tdev->tod_arp_update)
344 tdev->tod_arp_update(tdev, rt);
349 * offload_get_phys_egress - find the physical egress device
350 * @root_dev: the root device anchoring the search
351 * @so: the socket used to determine egress port in bonding mode
352 * @context: in bonding mode, indicates a connection set up or failover
354 * Given a root network device it returns the physical egress device that is a
355 * descendant of the root device. The root device may be either a physical
356 * device, in which case it is the device returned, or a virtual device, such
357 * as a VLAN or bonding device. In case of a bonding device the search
358 * considers the decisions of the bonding device given its mode to locate the
359 * correct egress device.
362 offload_get_phys_egress(struct ifnet *root_dev, struct socket *so, int context)
366 while (root_dev && ifnet_is_offload(root_dev)) {
367 if (root_dev->tod_priv_flags & IFF_802_1Q_VLAN)
368 root_dev = VLAN_DEV_INFO(root_dev)->real_dev;
369 else if (root_dev->tod_flags & IFF_MASTER)
370 root_dev = toe_bond_get_slave(root_dev, sk, context);
379 toecore_load(module_t mod, int cmd, void *arg)
385 mtx_init(&offload_db_lock, "toedev lock", NULL, MTX_DEF);
386 TAILQ_INIT(&offload_dev_list);
387 TAILQ_INIT(&offload_module_list);
392 mtx_lock(&offload_db_lock);
393 if (!TAILQ_EMPTY(&offload_dev_list) ||
394 !TAILQ_EMPTY(&offload_module_list)) {
396 mtx_unlock(&offload_db_lock);
399 mtx_unlock(&offload_db_lock);
400 mtx_destroy(&offload_db_lock);
413 static moduledata_t mod_data= {
419 MODULE_VERSION(toecore, 1);
420 DECLARE_MODULE(toecore, mod_data, SI_SUB_EXEC, SI_ORDER_ANY);