diff --git a/route.go b/route.go index 4a3e8235..ffad5d39 100644 --- a/route.go +++ b/route.go @@ -50,6 +50,7 @@ type Route struct { NewDst Destination Encap Encap Via Destination + Realm int MTU int Window int Rtt int @@ -95,6 +96,7 @@ func (r Route) String() string { } elems = append(elems, fmt.Sprintf("Flags: %s", r.ListFlags())) elems = append(elems, fmt.Sprintf("Table: %d", r.Table)) + elems = append(elems, fmt.Sprintf("Realm: %d", r.Realm)) return fmt.Sprintf("{%s}", strings.Join(elems, " ")) } @@ -108,6 +110,7 @@ func (r Route) Equal(x Route) bool { nexthopInfoSlice(r.MultiPath).Equal(x.MultiPath) && r.Protocol == x.Protocol && r.Priority == x.Priority && + r.Realm == x.Realm && r.Table == x.Table && r.Type == x.Type && r.Tos == x.Tos && diff --git a/route_linux.go b/route_linux.go index 7168c8b7..fcfb7828 100644 --- a/route_linux.go +++ b/route_linux.go @@ -56,6 +56,7 @@ const ( RT_FILTER_PRIORITY RT_FILTER_MARK RT_FILTER_MASK + RT_FILTER_REALM ) const ( @@ -893,6 +894,11 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg native.PutUint32(b, uint32(route.Priority)) rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_PRIORITY, b)) } + if route.Realm > 0 { + b := make([]byte, 4) + native.PutUint32(b, uint32(route.Realm)) + rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_FLOW, b)) + } if route.Tos > 0 { msg.Tos = uint8(route.Tos) } @@ -1061,6 +1067,8 @@ func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64) continue case filterMask&RT_FILTER_TOS != 0 && route.Tos != filter.Tos: continue + case filterMask&RT_FILTER_REALM != 0 && route.Realm != filter.Realm: + continue case filterMask&RT_FILTER_OIF != 0 && route.LinkIndex != filter.LinkIndex: continue case filterMask&RT_FILTER_IIF != 0 && route.ILinkIndex != filter.ILinkIndex: @@ -1127,6 +1135,8 @@ func deserializeRoute(m []byte) (Route, error) { route.ILinkIndex = int(native.Uint32(attr.Value[0:4])) case unix.RTA_PRIORITY: route.Priority = int(native.Uint32(attr.Value[0:4])) + case unix.RTA_FLOW: + route.Realm = int(native.Uint32(attr.Value[0:4])) case unix.RTA_TABLE: route.Table = int(native.Uint32(attr.Value[0:4])) case unix.RTA_MULTIPATH: diff --git a/route_test.go b/route_test.go index 0f22970f..36f6a430 100644 --- a/route_test.go +++ b/route_test.go @@ -575,6 +575,7 @@ func TestRouteFilterAllTables(t *testing.T) { Type: unix.RTN_UNICAST, Tos: 14, Hoplimit: 100, + Realm: 328, } if err := RouteAdd(&route); err != nil { t.Fatal(err) @@ -588,7 +589,8 @@ func TestRouteFilterAllTables(t *testing.T) { Type: unix.RTN_UNICAST, Tos: 14, Hoplimit: 100, - }, RT_FILTER_DST|RT_FILTER_SRC|RT_FILTER_SCOPE|RT_FILTER_TABLE|RT_FILTER_TYPE|RT_FILTER_TOS|RT_FILTER_HOPLIMIT) + Realm: 328, + }, RT_FILTER_DST|RT_FILTER_SRC|RT_FILTER_SCOPE|RT_FILTER_TABLE|RT_FILTER_TYPE|RT_FILTER_TOS|RT_FILTER_HOPLIMIT|RT_FILTER_REALM) if err != nil { t.Fatal(err) } @@ -615,6 +617,9 @@ func TestRouteFilterAllTables(t *testing.T) { if route.Hoplimit != 100 { t.Fatal("Invalid Hoplimit. Route not added properly") } + if route.Realm != 328 { + t.Fatal("Invalid Realm. Route not added properly") + } } } @@ -658,6 +663,7 @@ func TestRouteExtraFields(t *testing.T) { Type: unix.RTN_UNICAST, Tos: 14, Hoplimit: 100, + Realm: 239, } if err := RouteAdd(&route); err != nil { t.Fatal(err) @@ -670,7 +676,8 @@ func TestRouteExtraFields(t *testing.T) { Type: unix.RTN_UNICAST, Tos: 14, Hoplimit: 100, - }, RT_FILTER_DST|RT_FILTER_SRC|RT_FILTER_SCOPE|RT_FILTER_TABLE|RT_FILTER_TYPE|RT_FILTER_TOS|RT_FILTER_HOPLIMIT) + Realm: 239, + }, RT_FILTER_DST|RT_FILTER_SRC|RT_FILTER_SCOPE|RT_FILTER_TABLE|RT_FILTER_TYPE|RT_FILTER_TOS|RT_FILTER_HOPLIMIT|RT_FILTER_REALM) if err != nil { t.Fatal(err) } @@ -696,6 +703,9 @@ func TestRouteExtraFields(t *testing.T) { if routes[0].Hoplimit != 100 { t.Fatal("Invalid Hoplimit. Route not added properly") } + if routes[0].Realm != 239 { + t.Fatal("Invalid Realm. Route not added properly") + } } func TestRouteMultiPath(t *testing.T) { @@ -920,6 +930,12 @@ func TestRouteEqual(t *testing.T) { Hoplimit: 1, Gw: net.IPv4(1, 1, 1, 1), }, + { + LinkIndex: 20, + Dst: nil, + Realm: 29, + Gw: net.IPv4(1, 1, 1, 1), + }, { LinkIndex: 20, Dst: nil, @@ -969,6 +985,19 @@ func TestRouteEqual(t *testing.T) { Type: unix.RTN_UNICAST, Hoplimit: 100, }, + { + LinkIndex: 3, + Dst: &net.IPNet{ + IP: net.IPv4(1, 1, 1, 1), + Mask: net.CIDRMask(32, 32), + }, + Src: net.IPv4(127, 3, 3, 3), + Scope: unix.RT_SCOPE_LINK, + Priority: 13, + Table: unix.RT_TABLE_MAIN, + Type: unix.RTN_UNICAST, + Realm: 129, + }, { LinkIndex: 10, MPLSDst: &mplsDst,