Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

neighbour.c 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. /*
  2. * Copyright (C) 2013 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  17. * 02110-1301, USA.
  18. */
  19. FILE_LICENCE ( GPL2_OR_LATER );
  20. #include <stdint.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <errno.h>
  24. #include <ipxe/iobuf.h>
  25. #include <ipxe/retry.h>
  26. #include <ipxe/timer.h>
  27. #include <ipxe/malloc.h>
  28. #include <ipxe/neighbour.h>
  29. /** @file
  30. *
  31. * Neighbour discovery
  32. *
  33. * This file implements the abstract functions of neighbour discovery,
  34. * independent of the underlying network protocol (e.g. ARP or NDP).
  35. *
  36. */
  37. /** Neighbour discovery minimum timeout */
  38. #define NEIGHBOUR_MIN_TIMEOUT ( TICKS_PER_SEC / 8 )
  39. /** Neighbour discovery maximum timeout */
  40. #define NEIGHBOUR_MAX_TIMEOUT ( TICKS_PER_SEC * 3 )
  41. /** The neighbour cache */
  42. struct list_head neighbours = LIST_HEAD_INIT ( neighbours );
  43. static void neighbour_expired ( struct retry_timer *timer, int over );
  44. /**
  45. * Free neighbour cache entry
  46. *
  47. * @v refcnt Reference count
  48. */
  49. static void neighbour_free ( struct refcnt *refcnt ) {
  50. struct neighbour *neighbour =
  51. container_of ( refcnt, struct neighbour, refcnt );
  52. /* Sanity check */
  53. assert ( list_empty ( &neighbour->tx_queue ) );
  54. /* Drop reference to network device */
  55. netdev_put ( neighbour->netdev );
  56. /* Free neighbour */
  57. free ( neighbour );
  58. }
  59. /**
  60. * Create neighbour cache entry
  61. *
  62. * @v netdev Network device
  63. * @v net_protocol Network-layer protocol
  64. * @v net_dest Destination network-layer address
  65. * @ret neighbour Neighbour cache entry, or NULL if allocation failed
  66. */
  67. static struct neighbour * neighbour_create ( struct net_device *netdev,
  68. struct net_protocol *net_protocol,
  69. const void *net_dest ) {
  70. struct neighbour *neighbour;
  71. /* Allocate and initialise entry */
  72. neighbour = zalloc ( sizeof ( *neighbour ) );
  73. if ( ! neighbour )
  74. return NULL;
  75. ref_init ( &neighbour->refcnt, neighbour_free );
  76. neighbour->netdev = netdev_get ( netdev );
  77. neighbour->net_protocol = net_protocol;
  78. memcpy ( neighbour->net_dest, net_dest,
  79. net_protocol->net_addr_len );
  80. timer_init ( &neighbour->timer, neighbour_expired, &neighbour->refcnt );
  81. neighbour->timer.min_timeout = NEIGHBOUR_MIN_TIMEOUT;
  82. neighbour->timer.max_timeout = NEIGHBOUR_MAX_TIMEOUT;
  83. INIT_LIST_HEAD ( &neighbour->tx_queue );
  84. /* Transfer ownership to cache */
  85. list_add ( &neighbour->list, &neighbours );
  86. DBGC ( neighbour, "NEIGHBOUR %s %s %s created\n", netdev->name,
  87. net_protocol->name, net_protocol->ntoa ( net_dest ) );
  88. return neighbour;
  89. }
  90. /**
  91. * Find neighbour cache entry
  92. *
  93. * @v netdev Network device
  94. * @v net_protocol Network-layer protocol
  95. * @v net_dest Destination network-layer address
  96. * @ret neighbour Neighbour cache entry, or NULL if not found
  97. */
  98. static struct neighbour * neighbour_find ( struct net_device *netdev,
  99. struct net_protocol *net_protocol,
  100. const void *net_dest ) {
  101. struct neighbour *neighbour;
  102. list_for_each_entry ( neighbour, &neighbours, list ) {
  103. if ( ( neighbour->netdev == netdev ) &&
  104. ( neighbour->net_protocol == net_protocol ) &&
  105. ( memcmp ( neighbour->net_dest, net_dest,
  106. net_protocol->net_addr_len ) == 0 ) ) {
  107. /* Move to start of cache */
  108. list_del ( &neighbour->list );
  109. list_add ( &neighbour->list, &neighbours );
  110. return neighbour;
  111. }
  112. }
  113. return NULL;
  114. }
  115. /**
  116. * Start neighbour discovery
  117. *
  118. * @v neighbour Neighbour cache entry
  119. * @v discovery Neighbour discovery protocol
  120. * @v net_source Source network-layer address
  121. */
  122. static void neighbour_discover ( struct neighbour *neighbour,
  123. struct neighbour_discovery *discovery,
  124. const void *net_source ) {
  125. struct net_device *netdev = neighbour->netdev;
  126. struct net_protocol *net_protocol = neighbour->net_protocol;
  127. /* Record discovery protocol and source network-layer address */
  128. neighbour->discovery = discovery;
  129. memcpy ( neighbour->net_source, net_source,
  130. net_protocol->net_addr_len );
  131. /* Start timer to trigger neighbour discovery */
  132. start_timer_nodelay ( &neighbour->timer );
  133. DBGC ( neighbour, "NEIGHBOUR %s %s %s discovering via %s\n",
  134. netdev->name, net_protocol->name,
  135. net_protocol->ntoa ( neighbour->net_dest ),
  136. neighbour->discovery->name );
  137. }
  138. /**
  139. * Complete neighbour discovery
  140. *
  141. * @v neighbour Neighbour cache entry
  142. * @v ll_dest Destination link-layer address
  143. */
  144. static void neighbour_discovered ( struct neighbour *neighbour,
  145. const void *ll_dest ) {
  146. struct net_device *netdev = neighbour->netdev;
  147. struct ll_protocol *ll_protocol = netdev->ll_protocol;
  148. struct net_protocol *net_protocol = neighbour->net_protocol;
  149. struct io_buffer *iobuf;
  150. int rc;
  151. /* Fill in link-layer address */
  152. memcpy ( neighbour->ll_dest, ll_dest, ll_protocol->ll_addr_len );
  153. DBGC ( neighbour, "NEIGHBOUR %s %s %s is %s %s\n", netdev->name,
  154. net_protocol->name, net_protocol->ntoa ( neighbour->net_dest ),
  155. ll_protocol->name, ll_protocol->ntoa ( neighbour->ll_dest ) );
  156. /* Stop retransmission timer */
  157. stop_timer ( &neighbour->timer );
  158. /* Transmit any packets in queue. Take out a temporary
  159. * reference on the entry to prevent it from going out of
  160. * scope during the call to net_tx().
  161. */
  162. ref_get ( &neighbour->refcnt );
  163. while ( ( iobuf = list_first_entry ( &neighbour->tx_queue,
  164. struct io_buffer, list )) != NULL){
  165. DBGC2 ( neighbour, "NEIGHBOUR %s %s %s transmitting deferred "
  166. "packet\n", netdev->name, net_protocol->name,
  167. net_protocol->ntoa ( neighbour->net_dest ) );
  168. list_del ( &iobuf->list );
  169. if ( ( rc = net_tx ( iobuf, netdev, net_protocol, ll_dest,
  170. netdev->ll_addr ) ) != 0 ) {
  171. DBGC ( neighbour, "NEIGHBOUR %s %s %s could not "
  172. "transmit deferred packet: %s\n",
  173. netdev->name, net_protocol->name,
  174. net_protocol->ntoa ( neighbour->net_dest ),
  175. strerror ( rc ) );
  176. /* Ignore error and continue */
  177. }
  178. }
  179. ref_put ( &neighbour->refcnt );
  180. }
  181. /**
  182. * Destroy neighbour cache entry
  183. *
  184. * @v neighbour Neighbour cache entry
  185. * @v rc Reason for destruction
  186. */
  187. static void neighbour_destroy ( struct neighbour *neighbour, int rc ) {
  188. struct net_device *netdev = neighbour->netdev;
  189. struct net_protocol *net_protocol = neighbour->net_protocol;
  190. struct io_buffer *iobuf;
  191. /* Take ownership from cache */
  192. list_del ( &neighbour->list );
  193. /* Stop timer */
  194. stop_timer ( &neighbour->timer );
  195. /* Discard any outstanding I/O buffers */
  196. while ( ( iobuf = list_first_entry ( &neighbour->tx_queue,
  197. struct io_buffer, list )) != NULL){
  198. DBGC2 ( neighbour, "NEIGHBOUR %s %s %s discarding deferred "
  199. "packet: %s\n", netdev->name, net_protocol->name,
  200. net_protocol->ntoa ( neighbour->net_dest ),
  201. strerror ( rc ) );
  202. list_del ( &iobuf->list );
  203. netdev_tx_err ( neighbour->netdev, iobuf, rc );
  204. }
  205. DBGC ( neighbour, "NEIGHBOUR %s %s %s destroyed: %s\n", netdev->name,
  206. net_protocol->name, net_protocol->ntoa ( neighbour->net_dest ),
  207. strerror ( rc ) );
  208. /* Drop remaining reference */
  209. ref_put ( &neighbour->refcnt );
  210. }
  211. /**
  212. * Handle neighbour timer expiry
  213. *
  214. * @v timer Retry timer
  215. * @v fail Failure indicator
  216. */
  217. static void neighbour_expired ( struct retry_timer *timer, int fail ) {
  218. struct neighbour *neighbour =
  219. container_of ( timer, struct neighbour, timer );
  220. struct net_device *netdev = neighbour->netdev;
  221. struct net_protocol *net_protocol = neighbour->net_protocol;
  222. struct neighbour_discovery *discovery =
  223. neighbour->discovery;
  224. const void *net_dest = neighbour->net_dest;
  225. const void *net_source = neighbour->net_source;
  226. int rc;
  227. /* If we have failed, destroy the cache entry */
  228. if ( fail ) {
  229. neighbour_destroy ( neighbour, -ETIMEDOUT );
  230. return;
  231. }
  232. /* Restart the timer */
  233. start_timer ( &neighbour->timer );
  234. /* Transmit neighbour request */
  235. if ( ( rc = discovery->tx_request ( netdev, net_protocol, net_dest,
  236. net_source ) ) != 0 ) {
  237. DBGC ( neighbour, "NEIGHBOUR %s %s %s could not transmit %s "
  238. "request: %s\n", netdev->name, net_protocol->name,
  239. net_protocol->ntoa ( neighbour->net_dest ),
  240. neighbour->discovery->name, strerror ( rc ) );
  241. /* Retransmit when timer expires */
  242. return;
  243. }
  244. }
  245. /**
  246. * Transmit packet, determining link-layer address via neighbour discovery
  247. *
  248. * @v iobuf I/O buffer
  249. * @v netdev Network device
  250. * @v discovery Neighbour discovery protocol
  251. * @v net_protocol Network-layer protocol
  252. * @v net_dest Destination network-layer address
  253. * @v net_source Source network-layer address
  254. * @v ll_source Source link-layer address
  255. * @ret rc Return status code
  256. */
  257. int neighbour_tx ( struct io_buffer *iobuf, struct net_device *netdev,
  258. struct net_protocol *net_protocol, const void *net_dest,
  259. struct neighbour_discovery *discovery,
  260. const void *net_source, const void *ll_source ) {
  261. struct neighbour *neighbour;
  262. /* Find or create neighbour cache entry */
  263. neighbour = neighbour_find ( netdev, net_protocol, net_dest );
  264. if ( ! neighbour ) {
  265. neighbour = neighbour_create ( netdev, net_protocol, net_dest );
  266. if ( ! neighbour )
  267. return -ENOMEM;
  268. neighbour_discover ( neighbour, discovery, net_source );
  269. }
  270. /* If a link-layer address is available then transmit
  271. * immediately, otherwise queue for later transmission.
  272. */
  273. if ( neighbour_has_ll_dest ( neighbour ) ) {
  274. return net_tx ( iobuf, netdev, net_protocol, neighbour->ll_dest,
  275. ll_source );
  276. } else {
  277. DBGC2 ( neighbour, "NEIGHBOUR %s %s %s deferring packet\n",
  278. netdev->name, net_protocol->name,
  279. net_protocol->ntoa ( net_dest ) );
  280. list_add_tail ( &iobuf->list, &neighbour->tx_queue );
  281. return -EAGAIN;
  282. }
  283. }
  284. /**
  285. * Update existing neighbour cache entry
  286. *
  287. * @v netdev Network device
  288. * @v net_protocol Network-layer protocol
  289. * @v net_dest Destination network-layer address
  290. * @v ll_dest Destination link-layer address
  291. * @ret rc Return status code
  292. */
  293. int neighbour_update ( struct net_device *netdev,
  294. struct net_protocol *net_protocol,
  295. const void *net_dest, const void *ll_dest ) {
  296. struct neighbour *neighbour;
  297. /* Find neighbour cache entry */
  298. neighbour = neighbour_find ( netdev, net_protocol, net_dest );
  299. if ( ! neighbour )
  300. return -ENOENT;
  301. /* Set destination address */
  302. neighbour_discovered ( neighbour, ll_dest );
  303. return 0;
  304. }
  305. /**
  306. * Define neighbour cache entry
  307. *
  308. * @v netdev Network device
  309. * @v net_protocol Network-layer protocol
  310. * @v net_dest Destination network-layer address
  311. * @v ll_dest Destination link-layer address, if known
  312. * @ret rc Return status code
  313. */
  314. int neighbour_define ( struct net_device *netdev,
  315. struct net_protocol *net_protocol,
  316. const void *net_dest, const void *ll_dest ) {
  317. struct neighbour *neighbour;
  318. /* Find or create neighbour cache entry */
  319. neighbour = neighbour_find ( netdev, net_protocol, net_dest );
  320. if ( ! neighbour ) {
  321. neighbour = neighbour_create ( netdev, net_protocol, net_dest );
  322. if ( ! neighbour )
  323. return -ENOMEM;
  324. }
  325. /* Set destination address */
  326. neighbour_discovered ( neighbour, ll_dest );
  327. return 0;
  328. }
  329. /**
  330. * Update neighbour cache on network device state change or removal
  331. *
  332. * @v netdev Network device
  333. */
  334. static void neighbour_flush ( struct net_device *netdev ) {
  335. struct neighbour *neighbour;
  336. struct neighbour *tmp;
  337. /* Remove all neighbour cache entries when a network device is closed */
  338. if ( ! netdev_is_open ( netdev ) ) {
  339. list_for_each_entry_safe ( neighbour, tmp, &neighbours, list )
  340. neighbour_destroy ( neighbour, -ENODEV );
  341. }
  342. }
  343. /** Neighbour driver (for net device notifications) */
  344. struct net_driver neighbour_net_driver __net_driver = {
  345. .name = "Neighbour",
  346. .notify = neighbour_flush,
  347. .remove = neighbour_flush,
  348. };
  349. /**
  350. * Discard some cached neighbour entries
  351. *
  352. * @ret discarded Number of cached items discarded
  353. */
  354. static unsigned int neighbour_discard ( void ) {
  355. struct neighbour *neighbour;
  356. /* Drop oldest cache entry, if any */
  357. neighbour = list_last_entry ( &neighbours, struct neighbour, list );
  358. if ( neighbour ) {
  359. neighbour_destroy ( neighbour, -ENOBUFS );
  360. return 1;
  361. } else {
  362. return 0;
  363. }
  364. }
  365. /**
  366. * Neighbour cache discarder
  367. *
  368. * Neighbour cache entries are deemed to have a high replacement cost,
  369. * since flushing an active neighbour cache entry midway through a TCP
  370. * transfer will cause substantial disruption.
  371. */
  372. struct cache_discarder neighbour_discarder __cache_discarder (CACHE_EXPENSIVE)={
  373. .discard = neighbour_discard,
  374. };