netdev_register.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. /****************************************************************************
  2. * net/netdev/netdev_register.c
  3. *
  4. * Copyright (C) 2007-2012, 2014-2015, 2017-2018 Gregory Nutt. All rights
  5. * reserved.
  6. * Author: Gregory Nutt <gnutt@nuttx.org>
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the
  17. * distribution.
  18. * 3. Neither the name NuttX nor the names of its contributors may be
  19. * used to endorse or promote products derived from this software
  20. * without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  25. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  26. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  27. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  28. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  29. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  30. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  32. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  33. * POSSIBILITY OF SUCH DAMAGE.
  34. *
  35. ****************************************************************************/
  36. /****************************************************************************
  37. * Included Files
  38. ****************************************************************************/
  39. #include <nuttx/config.h>
  40. #include <sys/socket.h>
  41. #include <stdio.h>
  42. #include <semaphore.h>
  43. #include <assert.h>
  44. #include <string.h>
  45. #include <errno.h>
  46. #include <debug.h>
  47. #include <net/if.h>
  48. #include <net/ethernet.h>
  49. #include <nuttx/net/netconfig.h>
  50. #include <nuttx/net/netdev.h>
  51. #include <nuttx/net/ethernet.h>
  52. #include <nuttx/net/bluetooth.h>
  53. #include "utils/utils.h"
  54. #include "igmp/igmp.h"
  55. #include "mld/mld.h"
  56. #include "netdev/netdev.h"
  57. /****************************************************************************
  58. * Pre-processor Definitions
  59. ****************************************************************************/
  60. #define NETDEV_ETH_FORMAT "eth%d"
  61. #define NETDEV_LO_FORMAT "lo"
  62. #define NETDEV_SLIP_FORMAT "sl%d"
  63. #define NETDEV_TUN_FORMAT "tun%d"
  64. #define NETDEV_BNEP_FORMAT "bnep%d"
  65. #define NETDEV_PAN_FORMAT "pan%d"
  66. #define NETDEV_WLAN_FORMAT "wlan%d"
  67. #define NETDEV_WPAN_FORMAT "wpan%d"
  68. #if defined(CONFIG_DRIVERS_IEEE80211) /* Usually also has CONFIG_NET_ETHERNET */
  69. # define NETDEV_DEFAULT_FORMAT NETDEV_WLAN_FORMAT
  70. #elif defined(CONFIG_NET_ETHERNET)
  71. # define NETDEV_DEFAULT_FORMAT NETDEV_ETH_FORMAT
  72. #elif defined(CONFIG_NET_6LOWPAN)
  73. # define NETDEV_DEFAULT_FORMAT NETDEV_WPAN_FORMAT
  74. #elif defined(CONFIG_NET_SLIP)
  75. # define NETDEV_DEFAULT_FORMAT NETDEV_SLIP_FORMAT
  76. #elif defined(CONFIG_NET_TUN)
  77. # define NETDEV_DEFAULT_FORMAT NETDEV_TUN_FORMAT
  78. #else /* if defined(CONFIG_NET_LOOPBACK) */
  79. # define NETDEV_DEFAULT_FORMAT NETDEV_LO_FORMAT
  80. #endif
  81. /****************************************************************************
  82. * Public Data
  83. ****************************************************************************/
  84. /* List of registered Ethernet device drivers */
  85. struct net_driver_s *g_netdevices = NULL;
  86. #ifdef CONFIG_NETDEV_IFINDEX
  87. /* The set of network devices that have been registered. This is used to
  88. * assign a unique device index to the newly registered device.
  89. *
  90. * REVISIT: The width of g_nassigned limits the number of registered
  91. * devices to 32 (MAX_IFINDEX).
  92. */
  93. uint32_t g_devset;
  94. /* The set of network devices that have been freed. The purpose of this
  95. * set is to postpone reuse of a interface index for as long as possible,
  96. * i.e., don't reuse an interface index until all of the possible indices
  97. * have been used.
  98. */
  99. uint32_t g_devfreed;
  100. #endif
  101. /****************************************************************************
  102. * Private Functions
  103. ****************************************************************************/
  104. /****************************************************************************
  105. * Name: find_devnum
  106. *
  107. * Description:
  108. * Given a device name format string, find the next device number for the
  109. * class of device represented by that format string.
  110. *
  111. * Input Parameters:
  112. * devfmt - The device format string
  113. *
  114. * Returned Value:
  115. * The next device number for that device class
  116. *
  117. ****************************************************************************/
  118. static int find_devnum(FAR const char *devfmt)
  119. {
  120. FAR struct net_driver_s *curr;
  121. size_t fmt_size;
  122. int result = 0;
  123. fmt_size = strlen(devfmt);
  124. /* Assumed that devfmt is xxx%d */
  125. DEBUGASSERT(fmt_size > 2);
  126. fmt_size -= 2;
  127. /* Search the list of currently registered network devices */
  128. for (curr = g_netdevices; curr; curr = curr->flink )
  129. {
  130. /* Does this device name match the format we were given? */
  131. if (strncmp(curr->d_ifname, devfmt, fmt_size) == 0)
  132. {
  133. /* Yes.. increment the candidate device number */
  134. result++;
  135. }
  136. }
  137. /* Return this next device number for this format */
  138. return result;
  139. }
  140. /****************************************************************************
  141. * Name: get_ifindex
  142. *
  143. * Description:
  144. * Assign a unique interface index to the device.
  145. *
  146. * Input Parameters:
  147. * None
  148. *
  149. * Returned Value:
  150. * The interface index assigned to the device. -ENOSPC is returned if
  151. * more the MAX_IFINDEX names have been assigned.
  152. *
  153. ****************************************************************************/
  154. #ifdef CONFIG_NETDEV_IFINDEX
  155. static int get_ifindex(void)
  156. {
  157. uint32_t devset;
  158. int ndx;
  159. /* Try to postpone re-using interface indices as long as possible */
  160. devset = g_devset | g_devfreed;
  161. if (devset == 0xffffffff)
  162. {
  163. /* Time start re-using interface indices */
  164. devset = g_devset;
  165. g_devfreed = 0;
  166. }
  167. /* Search for an unused index */
  168. for (ndx = 0; ndx < MAX_IFINDEX; ndx++)
  169. {
  170. uint32_t bit = 1L << ndx;
  171. if ((devset & bit) == 0)
  172. {
  173. /* Indicate that this index is in use */
  174. g_devset |= bit;
  175. /* NOTE that the index + 1 is returned. Zero is reserved to
  176. * mean no-index in the POSIX standards.
  177. */
  178. return ndx + 1;
  179. }
  180. }
  181. return -ENOSPC;
  182. }
  183. #endif
  184. /****************************************************************************
  185. * Public Functions
  186. ****************************************************************************/
  187. /****************************************************************************
  188. * Name: netdev_register
  189. *
  190. * Description:
  191. * Register a network device driver and assign a name to it so that it can
  192. * be found in subsequent network ioctl operations on the device.
  193. *
  194. * A custom, device-specific interface name format string may be selected
  195. * by putting that format string into the device structure's d_ifname[]
  196. * array before calling netdev_register(). Otherwise, the d_ifname[] must
  197. * be zeroed on entry.
  198. *
  199. * Input Parameters:
  200. * dev - The device driver structure to be registered.
  201. * lltype - Link level protocol used by the driver (Ethernet, SLIP, TUN, ...
  202. * ...
  203. *
  204. * Returned Value:
  205. * 0:Success; negated errno on failure
  206. *
  207. * Assumptions:
  208. * Called during system bring-up, but also when a removable network
  209. * device is installed.
  210. *
  211. ****************************************************************************/
  212. int netdev_register(FAR struct net_driver_s *dev, enum net_lltype_e lltype)
  213. {
  214. FAR char devfmt_str[IFNAMSIZ];
  215. FAR const char *devfmt;
  216. int devnum;
  217. #ifdef CONFIG_NETDEV_IFINDEX
  218. int ifindex;
  219. #endif
  220. if (dev != NULL)
  221. {
  222. /* Set the protocol used by the device and the size of the link
  223. * header used by this protocol.
  224. */
  225. switch (lltype)
  226. {
  227. #ifdef CONFIG_NET_LOOPBACK
  228. case NET_LL_LOOPBACK: /* Local loopback */
  229. dev->d_llhdrlen = 0;
  230. dev->d_pktsize = NET_LO_PKTSIZE;
  231. devfmt = NETDEV_LO_FORMAT;
  232. break;
  233. #endif
  234. #ifdef CONFIG_NET_ETHERNET
  235. case NET_LL_ETHERNET: /* Ethernet */
  236. dev->d_llhdrlen = ETH_HDRLEN;
  237. dev->d_pktsize = CONFIG_NET_ETH_PKTSIZE;
  238. devfmt = NETDEV_ETH_FORMAT;
  239. break;
  240. #endif
  241. #ifdef CONFIG_DRIVERS_IEEE80211
  242. case NET_LL_IEEE80211: /* IEEE 802.11 */
  243. dev->d_llhdrlen = ETH_HDRLEN;
  244. dev->d_pktsize = CONFIG_NET_ETH_PKTSIZE;
  245. devfmt = NETDEV_WLAN_FORMAT;
  246. break;
  247. #endif
  248. #ifdef CONFIG_NET_BLUETOOTH
  249. case NET_LL_BLUETOOTH: /* Bluetooth */
  250. dev->d_llhdrlen = BLUETOOTH_MAX_HDRLEN; /* Determined at runtime */
  251. #ifdef CONFIG_NET_6LOWPAN
  252. dev->d_pktsize = CONFIG_NET_6LOWPAN_PKTSIZE;
  253. #endif
  254. devfmt = NETDEV_BNEP_FORMAT;
  255. break;
  256. #endif
  257. #if defined(CONFIG_NET_6LOWPAN) || defined(CONFIG_NET_IEEE802154)
  258. case NET_LL_IEEE802154: /* IEEE 802.15.4 MAC */
  259. case NET_LL_PKTRADIO: /* Non-IEEE 802.15.4 packet radio */
  260. dev->d_llhdrlen = 0; /* Determined at runtime */
  261. #ifdef CONFIG_NET_6LOWPAN
  262. dev->d_pktsize = CONFIG_NET_6LOWPAN_PKTSIZE;
  263. #endif
  264. devfmt = NETDEV_WPAN_FORMAT;
  265. break;
  266. #endif
  267. #ifdef CONFIG_NET_SLIP
  268. case NET_LL_SLIP: /* Serial Line Internet Protocol (SLIP) */
  269. dev->d_llhdrlen = 0;
  270. dev->d_pktsize = CONFIG_NET_SLIP_PKTSIZE;
  271. devfmt = NETDEV_SLIP_FORMAT;
  272. break;
  273. #endif
  274. #ifdef CONFIG_NET_TUN
  275. case NET_LL_TUN: /* Virtual Network Device (TUN) */
  276. dev->d_llhdrlen = 0; /* This will be overwritten by tun_ioctl
  277. * if used as a TAP (layer 2) device */
  278. dev->d_pktsize = CONFIG_NET_TUN_PKTSIZE;
  279. devfmt = NETDEV_TUN_FORMAT;
  280. break;
  281. #endif
  282. default:
  283. nerr("ERROR: Unrecognized link type: %d\n", lltype);
  284. return -EINVAL;
  285. }
  286. /* Remember the verified link type */
  287. dev->d_lltype = (uint8_t)lltype;
  288. /* There are no clients of the device yet */
  289. dev->d_conncb = NULL;
  290. dev->d_devcb = NULL;
  291. /* We need exclusive access for the following operations */
  292. net_lock();
  293. #ifdef CONFIG_NETDEV_IFINDEX
  294. ifindex = get_ifindex();
  295. if (ifindex < 0)
  296. {
  297. return ifindex;
  298. }
  299. dev->d_ifindex = (uint8_t)ifindex;
  300. #endif
  301. /* Get the next available device number and assign a device name to
  302. * the interface
  303. */
  304. /* Check if the caller has provided a user device-specific interface
  305. * name format string (in d_ifname).
  306. */
  307. if (dev->d_ifname[0] != '\0')
  308. {
  309. /* Copy the string in a temporary buffer. How do we know that the
  310. * string is valid and not just uninitialized memory? We don't.
  311. * Let's at least make certain that the format string is NUL
  312. * terminated.
  313. */
  314. dev->d_ifname[IFNAMSIZ - 1] = '\0';
  315. strncpy(devfmt_str, dev->d_ifname, IFNAMSIZ);
  316. /* Then use the content of the temporary buffer as the format
  317. * string.
  318. */
  319. devfmt = (FAR const char *)devfmt_str;
  320. }
  321. #ifdef CONFIG_NET_LOOPBACK
  322. /* The local loopback device is a special case: There can be only one
  323. * local loopback device so it is unnumbered.
  324. */
  325. if (lltype == NET_LL_LOOPBACK)
  326. {
  327. devnum = 0;
  328. }
  329. else
  330. #endif
  331. {
  332. devnum = find_devnum(devfmt);
  333. }
  334. /* Complete the device name by including the device number (if
  335. * included in the format).
  336. */
  337. snprintf(dev->d_ifname, IFNAMSIZ, devfmt, devnum);
  338. /* Add the device to the list of known network devices */
  339. dev->flink = g_netdevices;
  340. g_netdevices = dev;
  341. #ifdef CONFIG_NET_IGMP
  342. /* Configure the device for IGMP support */
  343. igmp_devinit(dev);
  344. #endif
  345. #ifdef CONFIG_NET_MLD
  346. /* Configure the device for MLD support */
  347. mld_devinit(dev);
  348. #endif
  349. net_unlock();
  350. #if defined(CONFIG_NET_ETHERNET) || defined(CONFIG_DRIVERS_IEEE80211)
  351. ninfo("Registered MAC: %02x:%02x:%02x:%02x:%02x:%02x as dev: %s\n",
  352. dev->d_mac.ether.ether_addr_octet[0], dev->d_mac.ether.ether_addr_octet[1],
  353. dev->d_mac.ether.ether_addr_octet[2], dev->d_mac.ether.ether_addr_octet[3],
  354. dev->d_mac.ether.ether_addr_octet[4], dev->d_mac.ether.ether_addr_octet[5],
  355. dev->d_ifname);
  356. #else
  357. ninfo("Registered dev: %s\n", dev->d_ifname);
  358. #endif
  359. return OK;
  360. }
  361. return -EINVAL;
  362. }