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 toedev_registration_count++;
123 TAILQ_INSERT_HEAD(&offload_module_list, t, entry);
124 mtx_unlock(&offload_db_lock);
129 * unregister_tom - unregister a TCP Offload Module (TOM)
130 * @t: the offload module to register
132 * Unregister a TCP Offload Module (TOM). Note that this does not affect any
133 * TOE devices to which the TOM is already attached.
136 unregister_tom(struct tom_info *t)
138 mtx_lock(&offload_db_lock);
139 TAILQ_REMOVE(&offload_module_list, t, entry);
140 mtx_unlock(&offload_db_lock);
145 * Find an offload device by name. Must be called with offload_db_lock held.
147 static struct toedev *
148 __find_offload_dev_by_name(const char *name)
152 TAILQ_FOREACH(dev, &offload_dev_list, entry) {
153 if (!strncmp(dev->tod_name, name, TOENAMSIZ))
160 * Returns true if an offload device is already registered.
161 * Must be called with the offload_db_lock held.
164 is_registered(const struct toedev *dev)
168 TAILQ_FOREACH(d, &offload_dev_list, entry) {
176 * Finalize the name of an offload device by assigning values to any format
177 * strings in its name.
180 assign_name(struct toedev *dev, const char *name, int limit)
184 for (i = 0; i < limit; ++i) {
187 if (snprintf(s, sizeof(s), name, i) >= sizeof(s))
188 return -1; /* name too long */
189 if (!__find_offload_dev_by_name(s)) {
190 strcpy(dev->tod_name, s);
198 * register_toedev - register a TOE device
200 * @name: a name template for the device
202 * Register a TOE device and try to attach an appropriate TCP offload module
203 * to it. @name is a template that may contain at most one %d format
207 register_toedev(struct toedev *dev, const char *name)
213 * Validate the name template. Only one %d allowed and name must be
214 * a valid filename so it can appear in sysfs.
216 if (!name || !*name || !strcmp(name, ".") || !strcmp(name, "..") ||
220 p = strchr(name, '%');
221 if (p && (p[1] != 'd' || strchr(p + 2, '%')))
224 mtx_lock(&offload_db_lock);
225 if (is_registered(dev)) { /* device already registered */
230 if ((ret = assign_name(dev, name, 32)) != 0)
233 dev->tod_offload_mod = NULL;
234 TAILQ_INSERT_TAIL(&offload_dev_list, dev, entry);
236 mtx_unlock(&offload_db_lock);
241 * unregister_toedev - unregister a TOE device
244 * Unregister a TOE device. The device must not be attached to an offload
248 unregister_toedev(struct toedev *dev)
252 mtx_lock(&offload_db_lock);
253 if (!is_registered(dev)) {
257 if (is_attached(dev)) {
261 TAILQ_REMOVE(&offload_dev_list, dev, entry);
263 mtx_unlock(&offload_db_lock);
268 * activate_offload - activate an offload device
271 * Activate an offload device by locating an appropriate registered offload
272 * module. If no module is found the operation fails and may be retried at
276 activate_offload(struct toedev *dev)
280 mtx_lock(&offload_db_lock);
281 if (!is_registered(dev))
283 else if (!is_attached(dev))
284 ret = offload_attach(dev);
285 mtx_unlock(&offload_db_lock);
290 * toe_send - send a packet to a TOE device
294 * Sends an mbuf to a TOE driver after dealing with any active network taps.
297 toe_send(struct toedev *dev, struct mbuf *m)
301 critical_enter(); /* XXX neccessary? */
302 r = dev->tod_send(dev, m);
305 BPF_MTAP(dev->tod_lldev, m);
310 * toe_receive_mbuf - process n received TOE packets
311 * @dev: the toe device
312 * @m: an array of offload packets
313 * @n: the number of offload packets
315 * Process an array of ingress offload packets. Each packet is forwarded
316 * to any active network taps and then passed to the toe device's receive
317 * method. We optimize passing packets to the receive method by passing
318 * it the whole array at once except when there are active taps.
321 toe_receive_mbuf(struct toedev *dev, struct mbuf **m, int n)
323 if (__predict_true(!bpf_peers_present(dev->tod_lldev->if_bpf)))
324 return dev->tod_recv(dev, m, n);
326 for ( ; n; n--, m++) {
327 m[0]->m_pkthdr.rcvif = dev->tod_lldev;
328 BPF_MTAP(dev->tod_lldev, m[0]);
329 dev->tod_recv(dev, m, 1);
335 ifnet_is_offload(const struct ifnet *ifp)
337 return (ifp->if_flags & IFCAP_TOE);
341 toe_arp_update(struct rtentry *rt)
343 struct ifnet *ifp = rt->rt_ifp;
345 if (ifp && ifnet_is_offload(ifp)) {
346 struct toedev *tdev = TOEDEV(ifp);
348 if (tdev && tdev->tod_arp_update)
349 tdev->tod_arp_update(tdev, rt);
354 * offload_get_phys_egress - find the physical egress device
355 * @root_dev: the root device anchoring the search
356 * @so: the socket used to determine egress port in bonding mode
357 * @context: in bonding mode, indicates a connection set up or failover
359 * Given a root network device it returns the physical egress device that is a
360 * descendant of the root device. The root device may be either a physical
361 * device, in which case it is the device returned, or a virtual device, such
362 * as a VLAN or bonding device. In case of a bonding device the search
363 * considers the decisions of the bonding device given its mode to locate the
364 * correct egress device.
367 offload_get_phys_egress(struct ifnet *root_dev, struct socket *so, int context)
371 while (root_dev && ifnet_is_offload(root_dev)) {
372 if (root_dev->tod_priv_flags & IFF_802_1Q_VLAN)
373 root_dev = VLAN_DEV_INFO(root_dev)->real_dev;
374 else if (root_dev->tod_flags & IFF_MASTER)
375 root_dev = toe_bond_get_slave(root_dev, sk, context);
384 toecore_load(module_t mod, int cmd, void *arg)
390 mtx_init(&offload_db_lock, "toedev lock", NULL, MTX_DEF);
391 TAILQ_INIT(&offload_dev_list);
392 TAILQ_INIT(&offload_module_list);
397 mtx_lock(&offload_db_lock);
398 if (!TAILQ_EMPTY(&offload_dev_list) ||
399 !TAILQ_EMPTY(&offload_module_list)) {
401 mtx_unlock(&offload_db_lock);
404 mtx_unlock(&offload_db_lock);
405 mtx_destroy(&offload_db_lock);
418 static moduledata_t mod_data= {
424 MODULE_VERSION(toecore, 1);
425 DECLARE_MODULE(toecore, mod_data, SI_SUB_EXEC, SI_ORDER_ANY);