diff options
author | bms <bms@FreeBSD.org> | 2009-03-19 01:43:03 +0000 |
---|---|---|
committer | bms <bms@FreeBSD.org> | 2009-03-19 01:43:03 +0000 |
commit | 76f193cd692e42617fb7f33b9581e7e5a3da58f0 (patch) | |
tree | d8c3186aadc92c08ebcc649765a90704c2e1d233 /usr.bin/netstat | |
parent | be7293a078080bef32e2a64d792bfdfa0c65dead (diff) | |
download | FreeBSD-src-76f193cd692e42617fb7f33b9581e7e5a3da58f0.zip FreeBSD-src-76f193cd692e42617fb7f33b9581e7e5a3da58f0.tar.gz |
Introduce a number of changes to the MROUTING code.
This is purely a forwarding plane cleanup; no control plane
code is involved.
Summary:
* Split IPv4 and IPv6 MROUTING support. The static compile-time
kernel option remains the same, however, the modules may now
be built for IPv4 and IPv6 separately as ip_mroute_mod and
ip6_mroute_mod.
* Clean up the IPv4 multicast forwarding code to use BSD queue
and hash table constructs. Don't build our own timer abstractions
when ratecheck() and timevalclear() etc will do.
* Expose the multicast forwarding cache (MFC) and virtual interface
table (VIF) as sysctls, to reduce netstat's dependence on libkvm
for this information for running kernels.
* bandwidth meters however still require libkvm.
* Make the MFC hash table size a boot/load-time tunable ULONG,
net.inet.ip.mfchashsize (defaults to 256).
* Remove unused members from struct vif and struct mfc.
* Kill RSVP support, as no current RSVP implementation uses it.
These stubs could be moved to raw_ip.c.
* Don't share locks or initialization between IPv4 and IPv6.
* Don't use a static struct route_in6 in ip6_mroute.c.
The v6 code is still using a cached struct route_in6, this is
moved to mif6 for the time being.
* More cleanup remains to be merged from ip_mroute.c to ip6_mroute.c.
v4 path tested using ports/net/mcast-tools.
v6 changes are mostly mechanical locking and *have not* been tested.
As these changes partially break some kernel ABIs, they will not
be MFCed. There is a lot more work to be done here.
Reviewed by: Pavlin Radoslavov
Diffstat (limited to 'usr.bin/netstat')
-rw-r--r-- | usr.bin/netstat/main.c | 9 | ||||
-rw-r--r-- | usr.bin/netstat/mroute.c | 306 | ||||
-rw-r--r-- | usr.bin/netstat/netstat.h | 2 |
3 files changed, 196 insertions, 121 deletions
diff --git a/usr.bin/netstat/main.c b/usr.bin/netstat/main.c index 6eb313a..8b25ff5 100644 --- a/usr.bin/netstat/main.c +++ b/usr.bin/netstat/main.c @@ -82,8 +82,8 @@ static struct nlist nl[] = { { .n_name = "_rt_tables"}, #define N_MRTSTAT 3 { .n_name = "_mrtstat" }, -#define N_MFCTABLE 4 - { .n_name = "_mfctable" }, +#define N_MFCHASHTBL 4 + { .n_name = "_mfchashtbl" }, #define N_VIFTABLE 5 { .n_name = "_viftable" }, #define N_IPX 6 @@ -182,6 +182,8 @@ static struct nlist nl[] = { { .n_name = "_rip6stat" }, #define N_SCTPSTAT 53 { .n_name = "_sctpstat" }, +#define N_MFCTABLESIZE 54 + { .n_name = "_mfctablesize" }, { .n_name = NULL }, }; @@ -550,7 +552,8 @@ main(int argc, char *argv[]) #endif } else { if (af == AF_INET || af == AF_UNSPEC) - mroutepr(nl[N_MFCTABLE].n_value, + mroutepr(nl[N_MFCHASHTBL].n_value, + nl[N_MFCTABLESIZE].n_value, nl[N_VIFTABLE].n_value); #ifdef INET6 if (af == AF_INET6 || af == AF_UNSPEC) diff --git a/usr.bin/netstat/mroute.c b/usr.bin/netstat/mroute.c index dbce318..8009c30 100644 --- a/usr.bin/netstat/mroute.c +++ b/usr.bin/netstat/mroute.c @@ -67,124 +67,9 @@ __FBSDID("$FreeBSD$"); #include <stdlib.h> #include "netstat.h" -static void print_bw_meter(struct bw_meter *bw_meter, int *banner_printed); -void -mroutepr(u_long mfcaddr, u_long vifaddr) -{ - struct mfc *mfctable[MFCTBLSIZ]; - struct vif viftable[MAXVIFS]; - struct mfc mfc, *m; - struct vif *v; - vifi_t vifi; - int i; - int banner_printed; - int saved_numeric_addr; - vifi_t maxvif = 0; - size_t len; - - len = sizeof(mfctable); - if (live) { - if (sysctlbyname("net.inet.ip.mfctable", mfctable, &len, NULL, - 0) < 0) { - warn("sysctl: net.inet.ip.mfctable"); - return; - } - } else - kread(mfcaddr, (char *)mfctable, sizeof(mfctable)); - - len = sizeof(viftable); - if (live) { - if (sysctlbyname("net.inet.ip.viftable", viftable, &len, NULL, - 0) < 0) { - warn("sysctl: net.inet.ip.viftable"); - return; - } - } else - kread(vifaddr, (char *)viftable, sizeof(viftable)); - - saved_numeric_addr = numeric_addr; - numeric_addr = 1; - - banner_printed = 0; - for (vifi = 0, v = viftable; vifi < MAXVIFS; ++vifi, ++v) { - if (v->v_lcl_addr.s_addr == 0) - continue; - - maxvif = vifi; - if (!banner_printed) { - printf("\nIPv4 Virtual Interface Table\n" - " Vif Thresh Rate Local-Address " - "Remote-Address Pkts-In Pkts-Out\n"); - banner_printed = 1; - } - - printf(" %2u %6u %4d %-15.15s", - /* opposite math of add_vif() */ - vifi, v->v_threshold, v->v_rate_limit * 1000 / 1024, - routename(v->v_lcl_addr.s_addr)); - printf(" %-15.15s", (v->v_flags & VIFF_TUNNEL) ? - routename(v->v_rmt_addr.s_addr) : ""); - - printf(" %9lu %9lu\n", v->v_pkt_in, v->v_pkt_out); - } - if (!banner_printed) - printf("\nIPv4 Virtual Interface Table is empty\n"); - - banner_printed = 0; - for (i = 0; i < MFCTBLSIZ; ++i) { - m = mfctable[i]; - while(m) { - /* XXX KVM */ - kread((u_long)m, (char *)&mfc, sizeof mfc); - - if (!banner_printed) { - printf("\nIPv4 Multicast Forwarding Table\n" - " Origin Group " - " Packets In-Vif Out-Vifs:Ttls\n"); - banner_printed = 1; - } - - printf(" %-15.15s", routename(mfc.mfc_origin.s_addr)); - printf(" %-15.15s", routename(mfc.mfc_mcastgrp.s_addr)); - printf(" %9lu", mfc.mfc_pkt_cnt); - printf(" %3d ", mfc.mfc_parent); - for (vifi = 0; vifi <= maxvif; vifi++) { - if (mfc.mfc_ttls[vifi] > 0) - printf(" %u:%u", vifi, - mfc.mfc_ttls[vifi]); - } - printf("\n"); - - /* Print the bw meter information */ - { - struct bw_meter bw_meter, *bwm; - int banner_printed2 = 0; - - bwm = mfc.mfc_bw_meter; - while (bwm) { - /* XXX KVM */ - kread((u_long)bwm, (char *)&bw_meter, - sizeof bw_meter); - print_bw_meter(&bw_meter, - &banner_printed2); - bwm = bw_meter.bm_mfc_next; - } -#if 0 /* Don't ever print it? */ - if (! banner_printed2) - printf("\n No Bandwidth Meters\n"); -#endif - } - - m = mfc.mfc_next; - } - } - if (!banner_printed) - printf("\nIPv4 Multicast Forwarding Table is empty\n"); - - printf("\n"); - numeric_addr = saved_numeric_addr; -} +static void print_bw_meter(struct bw_meter *, int *); +static void print_mfc(struct mfc *, int, int *); static void print_bw_meter(struct bw_meter *bw_meter, int *banner_printed) @@ -262,6 +147,193 @@ print_bw_meter(struct bw_meter *bw_meter, int *banner_printed) printf("\n"); } +static void +print_mfc(struct mfc *m, int maxvif, int *banner_printed) +{ + struct bw_meter bw_meter, *bwm; + int bw_banner_printed; + int error; + vifi_t vifi; + + bw_banner_printed = 0; + + if (! *banner_printed) { + printf("\nIPv4 Multicast Forwarding Table\n" + " Origin Group " + " Packets In-Vif Out-Vifs:Ttls\n"); + *banner_printed = 1; + } + + printf(" %-15.15s", routename(m->mfc_origin.s_addr)); + printf(" %-15.15s", routename(m->mfc_mcastgrp.s_addr)); + printf(" %9lu", m->mfc_pkt_cnt); + printf(" %3d ", m->mfc_parent); + for (vifi = 0; vifi <= maxvif; vifi++) { + if (m->mfc_ttls[vifi] > 0) + printf(" %u:%u", vifi, m->mfc_ttls[vifi]); + } + printf("\n"); + + /* + * XXX We break the rules and try to use KVM to read the + * bandwidth meters, they are not retrievable via sysctl yet. + */ + bwm = m->mfc_bw_meter; + while (bwm != NULL) { + error = kread((u_long)bwm, (char *)&bw_meter, + sizeof(bw_meter)); + if (error) + break; + print_bw_meter(&bw_meter, &bw_banner_printed); + bwm = bw_meter.bm_mfc_next; + } +} + +void +mroutepr(u_long pmfchashtbl, u_long pmfctablesize, u_long pviftbl) +{ + struct vif viftable[MAXVIFS]; + struct vif *v; + struct mfc *m; + int banner_printed; + int saved_numeric_addr; + size_t len; + vifi_t vifi, maxvif; + + saved_numeric_addr = numeric_addr; + numeric_addr = 1; + + /* + * TODO: + * The VIF table will move to hanging off the struct if_info for + * each IPv4 configured interface. Currently it is statically + * allocated, and retrieved either using KVM or an opaque SYSCTL. + * + * This can't happen until the API documented in multicast(4) + * is itself refactored. The historical reason why VIFs use + * a separate ifindex space is entirely due to the legacy + * capability of the MROUTING code to create IPIP tunnels on + * the fly to support DVMRP. When gif(4) became available, this + * functionality was deprecated, as PIM does not use it. + */ + maxvif = 0; + + len = sizeof(viftable); + if (live) { + if (sysctlbyname("net.inet.ip.viftable", viftable, &len, NULL, + 0) < 0) { + warn("sysctl: net.inet.ip.viftable"); + return; + } + } else + kread(pviftbl, (char *)viftable, sizeof(viftable)); + + banner_printed = 0; + for (vifi = 0, v = viftable; vifi < MAXVIFS; ++vifi, ++v) { + if (v->v_lcl_addr.s_addr == 0) + continue; + + maxvif = vifi; + if (!banner_printed) { + printf("\nIPv4 Virtual Interface Table\n" + " Vif Thresh Local-Address " + "Remote-Address Pkts-In Pkts-Out\n"); + banner_printed = 1; + } + + printf(" %2u %6u %-15.15s", + /* opposite math of add_vif() */ + vifi, v->v_threshold, + routename(v->v_lcl_addr.s_addr)); + printf(" %-15.15s", (v->v_flags & VIFF_TUNNEL) ? + routename(v->v_rmt_addr.s_addr) : ""); + + printf(" %9lu %9lu\n", v->v_pkt_in, v->v_pkt_out); + } + if (!banner_printed) + printf("\nIPv4 Virtual Interface Table is empty\n"); + + banner_printed = 0; + + /* + * TODO: + * The MFC table will move into the AF_INET radix trie in future. + * In 8.x, it becomes a dynamically allocated structure referenced + * by a hashed LIST, allowing more than 256 entries w/o kernel tuning. + * + * If retrieved via opaque SYSCTL, the kernel will coalesce it into + * a static table for us. + * If retrieved via KVM, the hash list pointers must be followed. + */ + if (live) { + struct mfc *mfctable; + + len = 0; + if (sysctlbyname("net.inet.ip.mfctable", NULL, &len, NULL, + 0) < 0) { + warn("sysctl: net.inet.ip.mfctable"); + return; + } + + mfctable = malloc(len); + if (mfctable == NULL) { + warnx("malloc %lu bytes", (u_long)len); + return; + } + if (sysctlbyname("net.inet.ip.mfctable", mfctable, &len, NULL, + 0) < 0) { + free(mfctable); + warn("sysctl: net.inet.ip.mfctable"); + return; + } + + m = mfctable; + while (len >= sizeof(*m)) { + print_mfc(m++, maxvif, &banner_printed); + len -= sizeof(*m); + } + if (len != 0) + warnx("print_mfc: %d trailing bytes", len); + + free(mfctable); + } else { + LIST_HEAD(, mfc) *mfchashtbl; + u_long i, mfctablesize; + struct mfc mfc; + int error; + + error = kread(pmfctablesize, (char *)&mfctablesize, + sizeof(u_long)); + if (error) { + warn("kread: mfctablesize"); + return; + } + + len = sizeof(*mfchashtbl) * mfctablesize; + mfchashtbl = malloc(len); + if (mfchashtbl == NULL) { + warnx("malloc %lu bytes", (u_long)len); + return; + } + kread(pmfchashtbl, (char *)&mfchashtbl, len); + + for (i = 0; i < mfctablesize; i++) { + LIST_FOREACH(m, &mfchashtbl[i], mfc_hash) { + kread((u_long)m, (char *)&mfc, sizeof(mfc)); + print_mfc(m, maxvif, &banner_printed); + } + } + + free(mfchashtbl); + } + + if (!banner_printed) + printf("\nIPv4 Multicast Forwarding Table is empty\n"); + + printf("\n"); + numeric_addr = saved_numeric_addr; +} + void mrt_stats(u_long mstaddr) { diff --git a/usr.bin/netstat/netstat.h b/usr.bin/netstat/netstat.h index da76ff1..483bd6c 100644 --- a/usr.bin/netstat/netstat.h +++ b/usr.bin/netstat/netstat.h @@ -160,6 +160,6 @@ void tp_protopr(u_long, const char *, int, int); void tp_inproto(u_long); void tp_stats(caddr_t, caddr_t); -void mroutepr(u_long, u_long); +void mroutepr(u_long, u_long, u_long); void mrt_stats(u_long); void bpf_stats(char *); |