How to set route specific interface metrics under Mac OS X

2

0

UPDATE: I found a great answer to part of my problem here https://superuser.com/a/525592/169461. I was able to set priority for interface en1 (wifi). However, this is not specific enough, since it will now route all traffic through en1. I need to be able to set the metrics specifically for a route to my gateway and for a route to my NAS. So if you know how to do this on a Mac, please let me know.


OLD TITLE: Optimize routing on a machine with two ways to reach the gateway

I am trying to optimize the response time between my iMac, a NAS and a cablemodem. The iMac is situated in my office and connected to the internet through wifi to router 1 at 192.168.0.1 (Technicolor cablemodem) located in the living room.

The difficulty here is that I have a NAS at 192.168.0.100, which I want to be reachable at all times. It is also situated in the office, so I connected it to the the internet using an old Linksys router (router 2) with DD-WRT on it, using it as a wireless bridge. The address of that router is 192.168.0.2. Of course having an extra router in the office I also connected the iMac and the NAS to it using cables. This all works fine. The NAS is reachable through router 2 on interface en0*. The wireless connection is on en1. Here is the relevant output of netstat -nr.

*UPDATE2: please note that upon request I posted the complete routing table again. This is after I reversed priorities of en0 and en1 (see the UPDATE above). So now the NAS is reached through en1 and the default gateway through en1 as well. The point is still the same, how can I make OSX use the fastest interface for each route?

Routing tables

Internet:
Destination        Gateway            Flags        Refs      Use   Netif Expire
default            192.168.0.1        UGSc           75        0     en1
default            192.168.0.1        UGScI           1        0     en0
127                127.0.0.1          UCS             0        0     lo0
127.0.0.1          127.0.0.1          UH              5      285     lo0
169.254            link#5             UCS             1        0     en1
169.254            link#4             UCSI            0        0     en0
169.254.179.33     0:10:95:de:ad:7    UHLSW           0        0     en1   1171
192.168.0          link#5             UCS             2        0     en1
192.168.0          link#4             UCSI            3        0     en0
192.168.0.1/32     link#5             UCS             1        0     en1
192.168.0.1        link#4             UHLWIir         1        0     en0
192.168.0.1/32     link#4             UCSI            1        0     en0
192.168.0.1        cc:35:40:eb:57:e3  UHLWIir        77       24     en1   1089
192.168.0.11/32    link#5             UCS             1        0     en1
192.168.0.11       4:54:53:f:5d:a7    UHLWI           0        1     en0   1090
192.168.0.11       4:54:53:f:5d:a7    UHLWIi         22     2046     lo0
192.168.0.100      0:90:a9:b6:3c:5a   UHLWI           0        0     en0   1184
192.168.0.100      58:6d:8f:d7:d3:3e  UHLWIi          3       63     en1   1184
192.168.0.101/32   link#4             UCS             0        0     en0
192.168.0.255      ff:ff:ff:ff:ff:ff  UHLWbI          0        1     en0
192.168.0.255      ff:ff:ff:ff:ff:ff  UHLWbI          0        4     en1

UPDATE3: As suggested in the comments I tried to add a static route that is very specific and it works sometimes, it is just not persisted by Mac OS X: sudo route add 192.168.0.100/32 -iface en0. Which leads to the following entry in the routing table:

192.168.0.100/32   3c:7:54:34:5a:4b   ULSc            0        0     en0

Output of ifconfig:

en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
options=10b<RXCSUM,TXCSUM,VLAN_HWTAGGING,AV>
ether 3c:07:54:34:5a:4b 
inet6 fe80::3e07:54ff:fe34:5a4b%en0 prefixlen 64 scopeid 0x4 
inet 192.168.0.101 netmask 0xffffff00 broadcast 192.168.0.255
nd6 options=1<PERFORMNUD>
media: autoselect (1000baseT <full-duplex,flow-control>)
status: active
en1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
ether 04:54:53:0f:5d:a7 
inet6 fe80::654:53ff:fe0f:5da7%en1 prefixlen 64 scopeid 0x5 
inet 192.168.0.11 netmask 0xffffff00 broadcast 192.168.0.255
nd6 options=1<PERFORMNUD>
media: autoselect
status: active

Now I noticed that the network on the iMac sometimes is sluggish to respond and there seem to be hiccups in the connection. Using ping I found out that this is at least partly due to long response times. there is a huge variation in response times:

PING 192.168.0.1 (192.168.0.1): 56 data bytes
64 bytes from 192.168.0.1: icmp_seq=0 ttl=64 time=67.161 ms
64 bytes from 192.168.0.1: icmp_seq=1 ttl=64 time=86.217 ms
64 bytes from 192.168.0.1: icmp_seq=2 ttl=64 time=5.536 ms
64 bytes from 192.168.0.1: icmp_seq=3 ttl=64 time=26.307 ms
64 bytes from 192.168.0.1: icmp_seq=4 ttl=64 time=47.608 ms
64 bytes from 192.168.0.1: icmp_seq=5 ttl=64 time=67.585 ms
64 bytes from 192.168.0.1: icmp_seq=6 ttl=64 time=89.349 ms
64 bytes from 192.168.0.1: icmp_seq=7 ttl=64 time=8.408 ms
64 bytes from 192.168.0.1: icmp_seq=8 ttl=64 time=30.391 ms
64 bytes from 192.168.0.1: icmp_seq=9 ttl=64 time=51.700 ms
64 bytes from 192.168.0.1: icmp_seq=10 ttl=64 time=72.978 ms
64 bytes from 192.168.0.1: icmp_seq=11 ttl=64 time=94.858 ms

And all that while traceroute says:

1  192.168.0.1 (192.168.0.1) 36 bytes to 192.168.0.101  88.989 ms  1.824 ms  1.705 ms

So I suspect that some of the packages for the internet gateway are routed through the (slower) wireless bridge of router 2 on en0 and some are routed through en1, which is fast enough. Obviously my next step was to try and set a static route to the gateway by executing:

sudo route add -host 192.168.0.1 -iface en1

Which I thought would force any connection to the gateway to go through the wireless interface at en1. No such luck however: when I do this, I lose internet connectivity on the iMac, which is not even restored when I change the route back.

I am not an expert at setting routes manually, so the question is: What am I doing wrong here and what do I have to do to get the iMac to route all traffic (except packages to 192.168.0.2 and 192.168.0.100) through en1?

I guess one way would be to define different subnets, but I still want every machine to be reachable from anywhere. Also I am not sure how I would go about that. Other hints on optimizing traffic would also be appreciated.

titusn

Posted 2015-12-20T12:36:56.357

Reputation: 105

1

You should be changing the metric of the route, rather than modifying the network interface. Please add to the post the output of route -n. Try using the ifmetric package, because it accepts an interface parameter and modifies the routes for you. Otherwise, you need to use the route command with the metric parameter. Set the metric to a high value on the slow interface.

– harrymc – 2015-12-26T12:52:12.540

I added the output of route -n as requested. Interestingly it shows that if1 is not currently considered a route to 192.168.0.1. I will try to set the metric on the interfaces as suggested. Note that on Mac OS X the ifmetric package is not available by default. – titusn – 2015-12-26T18:20:09.880

Actually there seems to be no metric parameter in the Mac OS X version of route. So I ended up trying to change the connection priority, as mentioned in this answer: http://superuser.com/questions/472454/how-does-mac-osx-prioritize-network-interfaces-when-routing

– titusn – 2015-12-26T18:45:05.853

While this works to alleviate my normal response time, it also creates the problem that now response times from the NAS vary, which is of course also reachable through both interfaces. It would be great if anybody knew how to set interface metrics for specific routes on a Mac. – titusn – 2015-12-26T18:51:03.087

I'm not a Mac person, where it seems netstat -nr replaces route -n. The Mac might yet follow the rule of routes with a longer prefix taking priority. Try to add a route to 192.168.0.100/32 which having a 32-bit prefix might take priority. And why are all your routes duplicated for both en0 and en1? - Try to be more specific. Backup the routes table before manipulating. – harrymc – 2015-12-26T19:50:30.463

Ah yes, I removed the output of route -n get 192.168.0.1 again, because it was not instructive anymore. The routes are duplicated, because by default the Mac creates all of these. I left half of the routing table out here for brevity. – titusn – 2015-12-26T19:53:03.553

I don't have a Mac and I don't want to mislead you, so I think I will stop here. I think that the routes table is the right direction. Lots of documentation is available, but a Mac is required for experimenting. As you will need to override the default routes, segmenting the networks might be the easiest solution. Adding routes to the other segments will solve the connection problem. – harrymc – 2015-12-26T20:03:27.513

Please post your whole routing table, not just the snippets you selected. It will be impossible to give you a reasonable reply without it. – MariusMatutiae – 2015-12-28T16:50:23.793

I now added the whole routing table, although I don't really see the difference with leaving out a few addresses that have nothing to do with the issue. – titusn – 2015-12-28T20:29:18.350

Can you disable the wireless bridge on the old Linksys router? Then you won't have a route to your gateway via both interfaces. (You would need to use a different subnet on this NAS-only network.) – jbg – 2015-12-30T09:18:19.673

Answers

1

The simplest solution to this doesn't involve having to define (and find a way to persist) static routes.

I would recommend that you use a different subnet (over the same physical network) for storage.

  • Turn off DHCP on en0 on your Mac and set it to have a static IP on this new subnet on en0, with no gateway defined on that interface. Say, for example, 192.168.1.1 with subnet mask 255.255.255.0.

  • Give the NAS an IP on this subnet too. Say, for example, 192.168.1.2 with subnet mask 255.255.255.0.

  • Any other device on the network that needs to reach the NAS can also have an IP on this subnet and will be able to communicate with it. No special routing is necessary. It can even have two IP adresses, one on the 0.0 net and one on the 1.0 net, as long as only one of them has a gateway assigned.

  • Your Mac will now have one route to the gateway (en1, Wi-Fi) and one route to the NAS (en0, Ethernet).

jbg

Posted 2015-12-20T12:36:56.357

Reputation: 182

Sure, as I said at the end of the question that is a way (although it would force me to change the addresses of other computers). However, I mainly wanted to know if there is another way, because I think a network topology with two routes to the gateway should be possible, even with a Mac. – titusn – 2015-12-30T17:00:49.810

Yes, it is, with a new startup item script or a launchd service, running the “route” commands to install the routes on startup. It’s very untidy compared to the way I’m suggesting though, and more fragile (more likely to break when you make other changes). Even if we were doing this on our Linux servers and Juniper routers, which have much more routing functionality, we wouldn’t set it up with two gateways. – jbg – 2015-12-30T17:07:50.760

I agree, I didn't like the idea of using a script to persist the routes either. I will try out your solution. I want to see if it is going to work with auto-discovery and my network speaker. – titusn – 2015-12-30T17:31:43.587

If the auto-discovery uses Bonjour / multicast DNS, it will work fine. That also applies to the network speaker if it’s, e.g., AirPlay. Otherwise, the network speaker should continue to work over the existing 192.168.0.0/24 network, which isn’t being changed, unless it needs to access the NAS in which case things get slightly more complicated! – jbg – 2015-12-30T17:48:55.417

I tried it, it works mostly, but unfortunately one crucial part does not. My Linux machine which plays video's from the NAS (after Time Machine backups the most important usage) cannot reach it. The Linux laptop is located in the living room and is connected via WiFi to router 1. It cannot connect to the NAS, because it has to be on the 192.168.0.0 subnet to see the router. – titusn – 2016-01-01T22:42:38.400

It can have two addresses, one on each subnet. Just make sure its only gateway is the router. – jbg – 2016-01-01T22:53:29.607

1Hey thanks, that did the trick. I have been doing this for 20 years, but never knew about secondary IP addresses. Added that remark to your answer. – titusn – 2016-01-02T10:48:41.217