Monitoring a Netgear DM200

After a bit of stuffing about, I got our connection mostly set up how I want it: the modem (a DM200) is setup in a dumb-modem configuration. The pfSense box (A PC Engines APU) picks up the WAN IP via DHCP (so no more double-NAT), but our DHCP client is also configured to add an alias for the RFC1918 address in the same subnet as the router configuration. Changing the DHCP client was fun - I thought I’d broken something, so I kept messing with it, but it seems that AussieBB’s DHCP server will happily hand out your IP address to any DHCP client MAC that requests it, but will only actually send traffic to the new MAC after a delay of around ten minutes. So it worked first go, and I destroyed my pfSense configuration trying to work out why it wasn’t working, for no damned reason.

Anyway, after adding a simple NAT rule:

nat on $WAN  from 10.0.0.0/8 to 172.16.0.0/24 -> 172.16.0.2/32 port 1024:65535

and we’re able to access the router from inside the LAN anyway. This means that I can inspect things like the DSL line stats (though not much else, because in modem-only mode the DM200 has next to no configuration). So I knocked together a little script in PHP (ugh, I hate PHP so much, and I had to use PHP5.6 to boot because I can’t find any RRD modules for 7) to poll the router’s status page and dump it to an RRD:

<?php

# Configuration
$r_ip = '192.168.0.1';
$r_un = 'admin';
$r_pw = 'password';
$rrd_db = '/home/fwaggle/router_stats.rrd';

# Values to fetch from the router and the types to store them as in RRD
$values = array(
	'conn_down' => 'GAUGE',
    'conn_up' => 'GAUGE',
    'line_down' => 'GAUGE',
    'line_up' => 'GAUGE',
    'noise_down' => 'GAUGE',
    'noise_up' => 'GAUGE',
#    'lan_txpkts' => 'COUNTER', # these don't seem
#    'lan_rxpkts' => 'COUNTER'  # like they work...
);

# Now fetch the values from the router.
$ch = curl_init("http://$r_ip/RST_statistic.htm");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

$headers = array(
    'Content-Type:application/json',
    'Authorization: Basic '. base64_encode("$r_un:$r_pw")
);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$page = curl_exec($ch);
curl_close($ch);

# Basically grep the resulting HTML file for our desired values.
preg_match_all('/var (.+)="(.+)"/', $page, $matches);
foreach ($matches[1] as $key => $value)
{
	# All values start out stuffed as-is
	$router[$value] = $matches[2][$key];

	# translate bps values
	if (in_array($value, array('conn_down', 'conn_up')))
	{
		preg_match('/([0-9\.]+) ([A-Z])bps/', $router[$value], $m);
		$v = floatval($m[1]);
		switch ($m[2]) {
			case 'G': # optimistic?
				$v = $v * 1000.0;
			case 'M':
				$v = $v * 1000.0;
			case 'K':
				$v = $v * 1000.0;
		}
		if ($v > 0)
			$router[$value] = $v;
	}

	# translate dB values
	if (in_array($value, array('line_down', 'line_up', 'noise_down', 'noise_up')))
	{
		preg_match('/([0-9\.]+) dB/', $router[$value], $m);
		$v = floatval($m[1]);
		if ($v > 0)
			$router[$value] = $v;
	}	
}

# If the RRD doesn't exist, we're going to create it.
$rrd_sources = array();
foreach ($values as $key =>$value)
{
	$rrd_sources[] = "DS:$key:$value:300:0:U";
}

$rrd_settings = array_merge($rrd_sources, array(
	"--step", "60",
	"RRA:MIN:0:360:576",
	"RRA:MIN:0:30:576",
	"RRA:MIN:0:7:576",
	"RRA:AVERAGE:0:360:576",
	"RRA:AVERAGE:0:30:576",
	"RRA:AVERAGE:0:7:576",
	"RRA:AVERAGE:0:1:576",
	"RRA:MAX:0:360:576",
	"RRA:MAX:0:30:576",
	"RRA:MAX:0:7:576"
	));

if (!file_exists($rrd_db)) {
	print("Creating database...\n");
	$status = rrd_create($rrd_db, $rrd_settings);
	if (!$status)
		die ("Failure creating database!\n");
}

# Do RRD update.
$rrd_data ="N";
foreach ($values as $key =>$value)
{
	$rrd_data = $rrd_data . ":$router[$key]";
}

$status = rrd_update($rrd_db, array($rrd_data));
if (!$status) die("Failure updating RRD!\n");

It’s ugly, but it mostly works. Stuffed it in a cron job and came back a couple days later to draw some graphs, and the results make me want to call support even more (I reset the modem shortly after the script started running):

VDSL Sync Speed Graph - ~48 hours

That’s rather disappointing - the 2:1 ratio between downstream and upstream is nice, but it’s a significant hit to what we should be able to achieve considering how close we are to the node. Seriously bitter for my country’s federal government’s piss-poor handling of what should have been a nation-building project.

Update - 2017-10-16: I called AussieBB’s support, as this morning the sync rate for the downstream had dropped to about 31mbps - a proper 2:1 ratio - and they were busy so I pressed the # key to leave a callback message. They got back to me less than 5 hours later, and I was pleasantly surprised how prepared they were before calling. Ran some line tests with the modem disconnected, and it seems it’s unlikely I’m actually connected to the node that’s next door - if I am, then our loop must go a fair distance around the block before reaching it. Awesome.

I sent them the last few days’ graphs, but I’m not too optimistic they’re able to do much from their end. Very impressed with their service so far - it’s just the NBN in general that’s really disappointing.

Update 2019-01-20: I can’t remember the pfSense setting to do this, but in the backup XML file the settings are called alias-address and alias-subnet. In dhclient.conf, the settings look like this (lifted from the sample configuration in the manpage):

alias {
    interface "eth0";
    fixed-address 172.16.0.2;
    option subnet-mask 255.255.255.0;
}

The only downside to this configuration is that it’s not really a static IP, it only exists when dhcp is able to acquire a lease as well. That means that the IP address is probably not available for you to check your modem’s stats when you really need it, such as when the line is down. I’ve not yet worked out a decent solution to that problem.

Horsham, VIC, Australia fwaggle

Published:


Modified:


Filed under:


Location:

Horsham, VIC, Australia

Navigation: Older Entry Newer Entry