]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/net/if_llatbl.c
MFhead @ r286584
[FreeBSD/FreeBSD.git] / sys / net / if_llatbl.c
1 /*
2  * Copyright (c) 2004 Luigi Rizzo, Alessandro Cerri. All rights reserved.
3  * Copyright (c) 2004-2008 Qing Li. All rights reserved.
4  * Copyright (c) 2008 Kip Macy. All rights reserved.
5  * 
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 
15  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include "opt_ddb.h"
31 #include "opt_inet.h"
32 #include "opt_inet6.h"
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/malloc.h>
37 #include <sys/mbuf.h>
38 #include <sys/syslog.h>
39 #include <sys/sysctl.h>
40 #include <sys/socket.h>
41 #include <sys/kernel.h>
42 #include <sys/lock.h>
43 #include <sys/mutex.h>
44 #include <sys/rwlock.h>
45
46 #ifdef DDB
47 #include <ddb/ddb.h>
48 #endif
49
50 #include <vm/uma.h>
51
52 #include <netinet/in.h>
53 #include <net/if_llatbl.h>
54 #include <net/if.h>
55 #include <net/if_dl.h>
56 #include <net/if_var.h>
57 #include <net/route.h>
58 #include <net/vnet.h>
59 #include <netinet/if_ether.h>
60 #include <netinet6/in6_var.h>
61 #include <netinet6/nd6.h>
62
63 MALLOC_DEFINE(M_LLTABLE, "lltable", "link level address tables");
64
65 static VNET_DEFINE(SLIST_HEAD(, lltable), lltables);
66 #define V_lltables      VNET(lltables)
67
68 static void vnet_lltable_init(void);
69
70 struct rwlock lltable_rwlock;
71 RW_SYSINIT(lltable_rwlock, &lltable_rwlock, "lltable_rwlock");
72
73 static void llentries_unlink(struct lltable *llt, struct llentries *head);
74
75 static void htable_unlink_entry(struct llentry *lle);
76 static void htable_link_entry(struct lltable *llt, struct llentry *lle);
77 static int htable_foreach_lle(struct lltable *llt, llt_foreach_cb_t *f,
78     void *farg);
79
80 /*
81  * Dump lle state for a specific address family.
82  */
83 static int
84 lltable_dump_af(struct lltable *llt, struct sysctl_req *wr)
85 {
86         int error;
87
88         LLTABLE_LOCK_ASSERT();
89
90         if (llt->llt_ifp->if_flags & IFF_LOOPBACK)
91                 return (0);
92         error = 0;
93
94         IF_AFDATA_RLOCK(llt->llt_ifp);
95         error = lltable_foreach_lle(llt,
96             (llt_foreach_cb_t *)llt->llt_dump_entry, wr);
97         IF_AFDATA_RUNLOCK(llt->llt_ifp);
98
99         return (error);
100 }
101
102 /*
103  * Dump arp state for a specific address family.
104  */
105 int
106 lltable_sysctl_dumparp(int af, struct sysctl_req *wr)
107 {
108         struct lltable *llt;
109         int error = 0;
110
111         LLTABLE_RLOCK();
112         SLIST_FOREACH(llt, &V_lltables, llt_link) {
113                 if (llt->llt_af == af) {
114                         error = lltable_dump_af(llt, wr);
115                         if (error != 0)
116                                 goto done;
117                 }
118         }
119 done:
120         LLTABLE_RUNLOCK();
121         return (error);
122 }
123
124 /*
125  * Common function helpers for chained hash table.
126  */
127
128 /*
129  * Runs specified callback for each entry in @llt.
130  * Caller does the locking.
131  *
132  */
133 static int
134 htable_foreach_lle(struct lltable *llt, llt_foreach_cb_t *f, void *farg)
135 {
136         struct llentry *lle, *next;
137         int i, error;
138
139         error = 0;
140
141         for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
142                 LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
143                         error = f(llt, lle, farg);
144                         if (error != 0)
145                                 break;
146                 }
147         }
148
149         return (error);
150 }
151
152 static void
153 htable_link_entry(struct lltable *llt, struct llentry *lle)
154 {
155         struct llentries *lleh;
156         uint32_t hashidx;
157
158         if ((lle->la_flags & LLE_LINKED) != 0)
159                 return;
160
161         IF_AFDATA_WLOCK_ASSERT(llt->llt_ifp);
162
163         hashidx = llt->llt_hash(lle, LLTBL_HASHTBL_SIZE);
164         lleh = &llt->lle_head[hashidx];
165
166         lle->lle_tbl  = llt;
167         lle->lle_head = lleh;
168         lle->la_flags |= LLE_LINKED;
169         LIST_INSERT_HEAD(lleh, lle, lle_next);
170 }
171
172 static void
173 htable_unlink_entry(struct llentry *lle)
174 {
175
176         if ((lle->la_flags & LLE_LINKED) != 0) {
177                 IF_AFDATA_WLOCK_ASSERT(lle->lle_tbl->llt_ifp);
178                 LIST_REMOVE(lle, lle_next);
179                 lle->la_flags &= ~(LLE_VALID | LLE_LINKED);
180 #if 0
181                 lle->lle_tbl = NULL;
182                 lle->lle_head = NULL;
183 #endif
184         }
185 }
186
187 struct prefix_match_data {
188         const struct sockaddr *prefix;
189         const struct sockaddr *mask;
190         struct llentries dchain;
191         u_int flags;
192 };
193
194 static int
195 htable_prefix_free_cb(struct lltable *llt, struct llentry *lle, void *farg)
196 {
197         struct prefix_match_data *pmd;
198
199         pmd = (struct prefix_match_data *)farg;
200
201         if (llt->llt_match_prefix(pmd->prefix, pmd->mask, pmd->flags, lle)) {
202                 LLE_WLOCK(lle);
203                 LIST_INSERT_HEAD(&pmd->dchain, lle, lle_chain);
204         }
205
206         return (0);
207 }
208
209 static void
210 htable_prefix_free(struct lltable *llt, const struct sockaddr *prefix,
211     const struct sockaddr *mask, u_int flags)
212 {
213         struct llentry *lle, *next;
214         struct prefix_match_data pmd;
215
216         bzero(&pmd, sizeof(pmd));
217         pmd.prefix = prefix;
218         pmd.mask = mask;
219         pmd.flags = flags;
220         LIST_INIT(&pmd.dchain);
221
222         IF_AFDATA_WLOCK(llt->llt_ifp);
223         /* Push matching lles to chain */
224         lltable_foreach_lle(llt, htable_prefix_free_cb, &pmd);
225
226         llentries_unlink(llt, &pmd.dchain);
227         IF_AFDATA_WUNLOCK(llt->llt_ifp);
228
229         LIST_FOREACH_SAFE(lle, &pmd.dchain, lle_chain, next)
230                 llt->llt_free_entry(llt, lle);
231 }
232
233 static void
234 llentries_unlink(struct lltable *llt, struct llentries *head)
235 {
236         struct llentry *lle, *next;
237
238         LIST_FOREACH_SAFE(lle, head, lle_chain, next)
239                 llt->llt_unlink_entry(lle);
240 }
241
242 /*
243  * Helper function used to drop all mbufs in hold queue.
244  *
245  * Returns the number of held packets, if any, that were dropped.
246  */
247 size_t
248 lltable_drop_entry_queue(struct llentry *lle)
249 {
250         size_t pkts_dropped;
251         struct mbuf *next;
252
253         LLE_WLOCK_ASSERT(lle);
254
255         pkts_dropped = 0;
256         while ((lle->la_numheld > 0) && (lle->la_hold != NULL)) {
257                 next = lle->la_hold->m_nextpkt;
258                 m_freem(lle->la_hold);
259                 lle->la_hold = next;
260                 lle->la_numheld--;
261                 pkts_dropped++;
262         }
263
264         KASSERT(lle->la_numheld == 0,
265                 ("%s: la_numheld %d > 0, pkts_droped %zd", __func__,
266                  lle->la_numheld, pkts_dropped));
267
268         return (pkts_dropped);
269 }
270
271 /*
272  * Deletes an address from the address table.
273  * This function is called by the timer functions
274  * such as arptimer() and nd6_llinfo_timer(), and
275  * the caller does the locking.
276  *
277  * Returns the number of held packets, if any, that were dropped.
278  */
279 size_t
280 llentry_free(struct llentry *lle)
281 {
282         struct lltable *llt;
283         size_t pkts_dropped;
284
285         LLE_WLOCK_ASSERT(lle);
286
287         if ((lle->la_flags & LLE_LINKED) != 0) {
288                 llt = lle->lle_tbl;
289
290                 IF_AFDATA_WLOCK_ASSERT(llt->llt_ifp);
291                 llt->llt_unlink_entry(lle);
292         }
293
294         pkts_dropped = lltable_drop_entry_queue(lle);
295
296         LLE_FREE_LOCKED(lle);
297
298         return (pkts_dropped);
299 }
300
301 /*
302  * (al)locate an llentry for address dst (equivalent to rtalloc for new-arp).
303  *
304  * If found the llentry * is returned referenced and unlocked.
305  */
306 struct llentry *
307 llentry_alloc(struct ifnet *ifp, struct lltable *lt,
308     struct sockaddr_storage *dst)
309 {
310         struct llentry *la;
311
312         IF_AFDATA_RLOCK(ifp);
313         la = lla_lookup(lt, LLE_EXCLUSIVE, (struct sockaddr *)dst);
314         IF_AFDATA_RUNLOCK(ifp);
315         if ((la == NULL) &&
316             (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0) {
317                 IF_AFDATA_WLOCK(ifp);
318                 la = lla_create(lt, 0, (struct sockaddr *)dst);
319                 IF_AFDATA_WUNLOCK(ifp);
320         }
321
322         if (la != NULL) {
323                 LLE_ADDREF(la);
324                 LLE_WUNLOCK(la);
325         }
326
327         return (la);
328 }
329
330 /*
331  * Free all entries from given table and free itself.
332  */
333
334 static int
335 lltable_free_cb(struct lltable *llt, struct llentry *lle, void *farg)
336 {
337         struct llentries *dchain;
338
339         dchain = (struct llentries *)farg;
340
341         LLE_WLOCK(lle);
342         LIST_INSERT_HEAD(dchain, lle, lle_chain);
343
344         return (0);
345 }
346
347 /*
348  * Free all entries from given table and free itself.
349  */
350 void
351 lltable_free(struct lltable *llt)
352 {
353         struct llentry *lle, *next;
354         struct llentries dchain;
355
356         KASSERT(llt != NULL, ("%s: llt is NULL", __func__));
357
358         LLTABLE_WLOCK();
359         SLIST_REMOVE(&V_lltables, llt, lltable, llt_link);
360         LLTABLE_WUNLOCK();
361
362         LIST_INIT(&dchain);
363         IF_AFDATA_WLOCK(llt->llt_ifp);
364         /* Push all lles to @dchain */
365         lltable_foreach_lle(llt, lltable_free_cb, &dchain);
366         llentries_unlink(llt, &dchain);
367         IF_AFDATA_WUNLOCK(llt->llt_ifp);
368
369         LIST_FOREACH_SAFE(lle, &dchain, lle_chain, next) {
370                 if (callout_stop(&lle->la_timer))
371                         LLE_REMREF(lle);
372                 llentry_free(lle);
373         }
374
375         free(llt, M_LLTABLE);
376 }
377
378 #if 0
379 void
380 lltable_drain(int af)
381 {
382         struct lltable  *llt;
383         struct llentry  *lle;
384         register int i;
385
386         LLTABLE_RLOCK();
387         SLIST_FOREACH(llt, &V_lltables, llt_link) {
388                 if (llt->llt_af != af)
389                         continue;
390
391                 for (i=0; i < LLTBL_HASHTBL_SIZE; i++) {
392                         LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
393                                 LLE_WLOCK(lle);
394                                 if (lle->la_hold) {
395                                         m_freem(lle->la_hold);
396                                         lle->la_hold = NULL;
397                                 }
398                                 LLE_WUNLOCK(lle);
399                         }
400                 }
401         }
402         LLTABLE_RUNLOCK();
403 }
404 #endif
405
406 void
407 lltable_prefix_free(int af, struct sockaddr *prefix, struct sockaddr *mask,
408     u_int flags)
409 {
410         struct lltable *llt;
411
412         LLTABLE_RLOCK();
413         SLIST_FOREACH(llt, &V_lltables, llt_link) {
414                 if (llt->llt_af != af)
415                         continue;
416
417                 llt->llt_prefix_free(llt, prefix, mask, flags);
418         }
419         LLTABLE_RUNLOCK();
420 }
421
422 /*
423  * Create a new lltable.
424  */
425 struct lltable *
426 lltable_init(struct ifnet *ifp, int af)
427 {
428         struct lltable *llt;
429         register int i;
430
431         llt = malloc(sizeof(struct lltable), M_LLTABLE, M_WAITOK);
432
433         llt->llt_af = af;
434         llt->llt_ifp = ifp;
435         for (i = 0; i < LLTBL_HASHTBL_SIZE; i++)
436                 LIST_INIT(&llt->lle_head[i]);
437
438         /* Set some default callbacks */
439         llt->llt_link_entry = htable_link_entry;
440         llt->llt_unlink_entry = htable_unlink_entry;
441         llt->llt_prefix_free = htable_prefix_free;
442         llt->llt_foreach_entry = htable_foreach_lle;
443
444         LLTABLE_WLOCK();
445         SLIST_INSERT_HEAD(&V_lltables, llt, llt_link);
446         LLTABLE_WUNLOCK();
447
448         return (llt);
449 }
450
451 /*
452  * External methods used by lltable consumers
453  */
454
455 int
456 lltable_foreach_lle(struct lltable *llt, llt_foreach_cb_t *f, void *farg)
457 {
458
459         return (llt->llt_foreach_entry(llt, f, farg));
460 }
461
462 void
463 lltable_link_entry(struct lltable *llt, struct llentry *lle)
464 {
465
466         llt->llt_link_entry(llt, lle);
467 }
468
469 void
470 lltable_unlink_entry(struct lltable *llt, struct llentry *lle)
471 {
472
473         llt->llt_unlink_entry(lle);
474 }
475
476 void
477 lltable_fill_sa_entry(const struct llentry *lle, struct sockaddr *sa)
478 {
479         struct lltable *llt;
480
481         llt = lle->lle_tbl;
482         llt->llt_fill_sa_entry(lle, sa);
483 }
484
485 struct ifnet *
486 lltable_get_ifp(const struct lltable *llt)
487 {
488
489         return (llt->llt_ifp);
490 }
491
492 int
493 lltable_get_af(const struct lltable *llt)
494 {
495
496         return (llt->llt_af);
497 }
498
499 /*
500  * Called in route_output when rtm_flags contains RTF_LLDATA.
501  */
502 int
503 lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
504 {
505         struct sockaddr_dl *dl =
506             (struct sockaddr_dl *)info->rti_info[RTAX_GATEWAY];
507         struct sockaddr *dst = (struct sockaddr *)info->rti_info[RTAX_DST];
508         struct ifnet *ifp;
509         struct lltable *llt;
510         struct llentry *lle;
511         u_int laflags = 0;
512         int error;
513
514         KASSERT(dl != NULL && dl->sdl_family == AF_LINK,
515             ("%s: invalid dl\n", __func__));
516
517         ifp = ifnet_byindex(dl->sdl_index);
518         if (ifp == NULL) {
519                 log(LOG_INFO, "%s: invalid ifp (sdl_index %d)\n",
520                     __func__, dl->sdl_index);
521                 return EINVAL;
522         }
523
524         /* XXX linked list may be too expensive */
525         LLTABLE_RLOCK();
526         SLIST_FOREACH(llt, &V_lltables, llt_link) {
527                 if (llt->llt_af == dst->sa_family &&
528                     llt->llt_ifp == ifp)
529                         break;
530         }
531         LLTABLE_RUNLOCK();
532         KASSERT(llt != NULL, ("Yep, ugly hacks are bad\n"));
533
534         error = 0;
535
536         switch (rtm->rtm_type) {
537         case RTM_ADD:
538                 /* Add static LLE */
539                 IF_AFDATA_WLOCK(ifp);
540                 lle = lla_create(llt, 0, dst);
541                 if (lle == NULL) {
542                         IF_AFDATA_WUNLOCK(ifp);
543                         return (ENOMEM);
544                 }
545
546
547                 bcopy(LLADDR(dl), &lle->ll_addr, ifp->if_addrlen);
548                 if ((rtm->rtm_flags & RTF_ANNOUNCE))
549                         lle->la_flags |= LLE_PUB;
550                 lle->la_flags |= LLE_VALID;
551 #ifdef INET6
552                 /*
553                  * ND6
554                  */
555                 if (dst->sa_family == AF_INET6)
556                         lle->ln_state = ND6_LLINFO_REACHABLE;
557 #endif
558                 /*
559                  * NB: arp and ndp always set (RTF_STATIC | RTF_HOST)
560                  */
561
562                 if (rtm->rtm_rmx.rmx_expire == 0) {
563                         lle->la_flags |= LLE_STATIC;
564                         lle->la_expire = 0;
565                 } else
566                         lle->la_expire = rtm->rtm_rmx.rmx_expire;
567                 laflags = lle->la_flags;
568                 LLE_WUNLOCK(lle);
569                 IF_AFDATA_WUNLOCK(ifp);
570 #ifdef INET
571                 /* gratuitous ARP */
572                 if ((laflags & LLE_PUB) && dst->sa_family == AF_INET)
573                         arprequest(ifp,
574                             &((struct sockaddr_in *)dst)->sin_addr,
575                             &((struct sockaddr_in *)dst)->sin_addr,
576                             (u_char *)LLADDR(dl));
577 #endif
578
579                 break;
580
581         case RTM_DELETE:
582                 IF_AFDATA_WLOCK(ifp);
583                 error = lla_delete(llt, 0, dst);
584                 IF_AFDATA_WUNLOCK(ifp);
585                 return (error == 0 ? 0 : ENOENT);
586
587         default:
588                 error = EINVAL;
589         }
590
591         return (error);
592 }
593
594 static void
595 vnet_lltable_init()
596 {
597
598         SLIST_INIT(&V_lltables);
599 }
600 VNET_SYSINIT(vnet_lltable_init, SI_SUB_PSEUDO, SI_ORDER_FIRST,
601     vnet_lltable_init, NULL);
602
603 #ifdef DDB
604 struct llentry_sa {
605         struct llentry          base;
606         struct sockaddr         l3_addr;
607 };
608
609 static void
610 llatbl_lle_show(struct llentry_sa *la)
611 {
612         struct llentry *lle;
613         uint8_t octet[6];
614
615         lle = &la->base;
616         db_printf("lle=%p\n", lle);
617         db_printf(" lle_next=%p\n", lle->lle_next.le_next);
618         db_printf(" lle_lock=%p\n", &lle->lle_lock);
619         db_printf(" lle_tbl=%p\n", lle->lle_tbl);
620         db_printf(" lle_head=%p\n", lle->lle_head);
621         db_printf(" la_hold=%p\n", lle->la_hold);
622         db_printf(" la_numheld=%d\n", lle->la_numheld);
623         db_printf(" la_expire=%ju\n", (uintmax_t)lle->la_expire);
624         db_printf(" la_flags=0x%04x\n", lle->la_flags);
625         db_printf(" la_asked=%u\n", lle->la_asked);
626         db_printf(" la_preempt=%u\n", lle->la_preempt);
627         db_printf(" ln_byhint=%u\n", lle->ln_byhint);
628         db_printf(" ln_state=%d\n", lle->ln_state);
629         db_printf(" ln_router=%u\n", lle->ln_router);
630         db_printf(" ln_ntick=%ju\n", (uintmax_t)lle->ln_ntick);
631         db_printf(" lle_refcnt=%d\n", lle->lle_refcnt);
632         bcopy(&lle->ll_addr.mac16, octet, sizeof(octet));
633         db_printf(" ll_addr=%02x:%02x:%02x:%02x:%02x:%02x\n",
634             octet[0], octet[1], octet[2], octet[3], octet[4], octet[5]);
635         db_printf(" la_timer=%p\n", &lle->la_timer);
636
637         switch (la->l3_addr.sa_family) {
638 #ifdef INET
639         case AF_INET:
640         {
641                 struct sockaddr_in *sin;
642                 char l3s[INET_ADDRSTRLEN];
643
644                 sin = (struct sockaddr_in *)&la->l3_addr;
645                 inet_ntoa_r(sin->sin_addr, l3s);
646                 db_printf(" l3_addr=%s\n", l3s);
647                 break;
648         }
649 #endif
650 #ifdef INET6
651         case AF_INET6:
652         {
653                 struct sockaddr_in6 *sin6;
654                 char l3s[INET6_ADDRSTRLEN];
655
656                 sin6 = (struct sockaddr_in6 *)&la->l3_addr;
657                 ip6_sprintf(l3s, &sin6->sin6_addr);
658                 db_printf(" l3_addr=%s\n", l3s);
659                 break;
660         }
661 #endif
662         default:
663                 db_printf(" l3_addr=N/A (af=%d)\n", la->l3_addr.sa_family);
664                 break;
665         }
666 }
667
668 DB_SHOW_COMMAND(llentry, db_show_llentry)
669 {
670
671         if (!have_addr) {
672                 db_printf("usage: show llentry <struct llentry *>\n");
673                 return;
674         }
675
676         llatbl_lle_show((struct llentry_sa *)addr);
677 }
678
679 static void
680 llatbl_llt_show(struct lltable *llt)
681 {
682         int i;
683         struct llentry *lle;
684
685         db_printf("llt=%p llt_af=%d llt_ifp=%p\n",
686             llt, llt->llt_af, llt->llt_ifp);
687
688         for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
689                 LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
690
691                         llatbl_lle_show((struct llentry_sa *)lle);
692                         if (db_pager_quit)
693                                 return;
694                 }
695         }
696 }
697
698 DB_SHOW_COMMAND(lltable, db_show_lltable)
699 {
700
701         if (!have_addr) {
702                 db_printf("usage: show lltable <struct lltable *>\n");
703                 return;
704         }
705
706         llatbl_llt_show((struct lltable *)addr);
707 }
708
709 DB_SHOW_ALL_COMMAND(lltables, db_show_all_lltables)
710 {
711         VNET_ITERATOR_DECL(vnet_iter);
712         struct lltable *llt;
713
714         VNET_FOREACH(vnet_iter) {
715                 CURVNET_SET_QUIET(vnet_iter);
716 #ifdef VIMAGE
717                 db_printf("vnet=%p\n", curvnet);
718 #endif
719                 SLIST_FOREACH(llt, &V_lltables, llt_link) {
720                         db_printf("llt=%p llt_af=%d llt_ifp=%p(%s)\n",
721                             llt, llt->llt_af, llt->llt_ifp,
722                             (llt->llt_ifp != NULL) ?
723                                 llt->llt_ifp->if_xname : "?");
724                         if (have_addr && addr != 0) /* verbose */
725                                 llatbl_llt_show(llt);
726                         if (db_pager_quit) {
727                                 CURVNET_RESTORE();
728                                 return;
729                         }
730                 }
731                 CURVNET_RESTORE();
732         }
733 }
734 #endif