summaryrefslogtreecommitdiffstats
path: root/usr.bin/netstat
diff options
context:
space:
mode:
authorbms <bms@FreeBSD.org>2009-03-19 01:43:03 +0000
committerbms <bms@FreeBSD.org>2009-03-19 01:43:03 +0000
commit76f193cd692e42617fb7f33b9581e7e5a3da58f0 (patch)
treed8c3186aadc92c08ebcc649765a90704c2e1d233 /usr.bin/netstat
parentbe7293a078080bef32e2a64d792bfdfa0c65dead (diff)
downloadFreeBSD-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.c9
-rw-r--r--usr.bin/netstat/mroute.c306
-rw-r--r--usr.bin/netstat/netstat.h2
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 *);
OpenPOWER on IntegriCloud