mirror of https://github.com/vishvananda/netlink
add protocol, priority, table, type, tos to route
This commit is contained in:
parent
a57a12c1b1
commit
dfdad47336
11
route.go
11
route.go
|
@ -24,16 +24,19 @@ const (
|
||||||
FLAG_PERVASIVE NextHopFlag = syscall.RTNH_F_PERVASIVE
|
FLAG_PERVASIVE NextHopFlag = syscall.RTNH_F_PERVASIVE
|
||||||
)
|
)
|
||||||
|
|
||||||
// Route represents a netlink route. A route is associated with a link,
|
// Route represents a netlink route.
|
||||||
// has a destination network, an optional source ip, and optional
|
|
||||||
// gateway. Advanced route parameters and non-main routing tables are
|
|
||||||
// currently not supported.
|
|
||||||
type Route struct {
|
type Route struct {
|
||||||
LinkIndex int
|
LinkIndex int
|
||||||
|
Iif int
|
||||||
Scope Scope
|
Scope Scope
|
||||||
Dst *net.IPNet
|
Dst *net.IPNet
|
||||||
Src net.IP
|
Src net.IP
|
||||||
Gw net.IP
|
Gw net.IP
|
||||||
|
Protocol int
|
||||||
|
Priority int
|
||||||
|
Table int
|
||||||
|
Type int
|
||||||
|
Tos int
|
||||||
Flags int
|
Flags int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,6 @@ func routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error {
|
||||||
return fmt.Errorf("one of Dst.IP, Src, or Gw must not be nil")
|
return fmt.Errorf("one of Dst.IP, Src, or Gw must not be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.Scope = uint8(route.Scope)
|
|
||||||
msg.Flags = uint32(route.Flags)
|
|
||||||
family := -1
|
family := -1
|
||||||
var rtAttrs []*nl.RtAttr
|
var rtAttrs []*nl.RtAttr
|
||||||
|
|
||||||
|
@ -79,8 +77,34 @@ func routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error {
|
||||||
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_GATEWAY, gwData))
|
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_GATEWAY, gwData))
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.Family = uint8(family)
|
if route.Table > 0 {
|
||||||
|
if route.Table >= 256 {
|
||||||
|
msg.Table = syscall.RT_TABLE_UNSPEC
|
||||||
|
b := make([]byte, 4)
|
||||||
|
native.PutUint32(b, uint32(route.Table))
|
||||||
|
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_TABLE, b))
|
||||||
|
} else {
|
||||||
|
msg.Table = uint8(route.Table)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if route.Priority > 0 {
|
||||||
|
b := make([]byte, 4)
|
||||||
|
native.PutUint32(b, uint32(route.Priority))
|
||||||
|
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_PRIORITY, b))
|
||||||
|
}
|
||||||
|
if route.Tos > 0 {
|
||||||
|
msg.Tos = uint8(route.Tos)
|
||||||
|
}
|
||||||
|
if route.Protocol > 0 {
|
||||||
|
msg.Protocol = uint8(route.Protocol)
|
||||||
|
}
|
||||||
|
if route.Type > 0 {
|
||||||
|
msg.Type = uint8(route.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.Scope = uint8(route.Scope)
|
||||||
|
msg.Family = uint8(family)
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
for _, attr := range rtAttrs {
|
for _, attr := range rtAttrs {
|
||||||
req.AddData(attr)
|
req.AddData(attr)
|
||||||
|
@ -103,8 +127,8 @@ func routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error {
|
||||||
// The list can be filtered by link and ip family.
|
// The list can be filtered by link and ip family.
|
||||||
func RouteList(link Link, family int) ([]Route, error) {
|
func RouteList(link Link, family int) ([]Route, error) {
|
||||||
req := nl.NewNetlinkRequest(syscall.RTM_GETROUTE, syscall.NLM_F_DUMP)
|
req := nl.NewNetlinkRequest(syscall.RTM_GETROUTE, syscall.NLM_F_DUMP)
|
||||||
msg := nl.NewIfInfomsg(family)
|
infmsg := nl.NewIfInfomsg(family)
|
||||||
req.AddData(msg)
|
req.AddData(infmsg)
|
||||||
|
|
||||||
msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWROUTE)
|
msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWROUTE)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -149,14 +173,19 @@ func RouteList(link Link, family int) ([]Route, error) {
|
||||||
|
|
||||||
// deserializeRoute decodes a binary netlink message into a Route struct
|
// deserializeRoute decodes a binary netlink message into a Route struct
|
||||||
func deserializeRoute(m []byte) (Route, error) {
|
func deserializeRoute(m []byte) (Route, error) {
|
||||||
route := Route{}
|
|
||||||
msg := nl.DeserializeRtMsg(m)
|
msg := nl.DeserializeRtMsg(m)
|
||||||
attrs, err := nl.ParseRouteAttr(m[msg.Len():])
|
attrs, err := nl.ParseRouteAttr(m[msg.Len():])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return route, err
|
return Route{}, err
|
||||||
|
}
|
||||||
|
route := Route{
|
||||||
|
Scope: Scope(msg.Scope),
|
||||||
|
Protocol: int(msg.Protocol),
|
||||||
|
Table: int(msg.Table),
|
||||||
|
Type: int(msg.Type),
|
||||||
|
Tos: int(msg.Tos),
|
||||||
|
Flags: int(msg.Flags),
|
||||||
}
|
}
|
||||||
route.Scope = Scope(msg.Scope)
|
|
||||||
route.Flags = int(msg.Flags)
|
|
||||||
|
|
||||||
native := nl.NativeEndian()
|
native := nl.NativeEndian()
|
||||||
for _, attr := range attrs {
|
for _, attr := range attrs {
|
||||||
|
@ -171,8 +200,13 @@ func deserializeRoute(m []byte) (Route, error) {
|
||||||
Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attr.Value)),
|
Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attr.Value)),
|
||||||
}
|
}
|
||||||
case syscall.RTA_OIF:
|
case syscall.RTA_OIF:
|
||||||
routeIndex := int(native.Uint32(attr.Value[0:4]))
|
route.LinkIndex = int(native.Uint32(attr.Value[0:4]))
|
||||||
route.LinkIndex = routeIndex
|
case syscall.RTA_IIF:
|
||||||
|
route.Iif = int(native.Uint32(attr.Value[0:4]))
|
||||||
|
case syscall.RTA_PRIORITY:
|
||||||
|
route.Priority = int(native.Uint32(attr.Value[0:4]))
|
||||||
|
case syscall.RTA_TABLE:
|
||||||
|
route.Table = int(native.Uint32(attr.Value[0:4]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return route, nil
|
return route, nil
|
||||||
|
|
|
@ -18,17 +18,19 @@ func TestRouteAddDel(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// bring the interface up
|
// bring the interface up
|
||||||
if err = LinkSetUp(link); err != nil {
|
if err := LinkSetUp(link); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// add a gateway route
|
// add a gateway route
|
||||||
_, dst, err := net.ParseCIDR("192.168.0.0/24")
|
dst := &net.IPNet{
|
||||||
|
IP: net.IPv4(192, 168, 0, 0),
|
||||||
|
Mask: net.CIDRMask(24, 32),
|
||||||
|
}
|
||||||
|
|
||||||
ip := net.ParseIP("127.1.1.1")
|
ip := net.IPv4(127, 1, 1, 1)
|
||||||
route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
|
route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
|
||||||
err = RouteAdd(&route)
|
if err := RouteAdd(&route); err != nil {
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
routes, err := RouteList(link, FAMILY_V4)
|
routes, err := RouteList(link, FAMILY_V4)
|
||||||
|
@ -36,10 +38,10 @@ func TestRouteAddDel(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if len(routes) != 1 {
|
if len(routes) != 1 {
|
||||||
t.Fatal("Link not added properly")
|
t.Fatal("Route not added properly")
|
||||||
}
|
}
|
||||||
|
|
||||||
dstIP := net.ParseIP("192.168.0.42")
|
dstIP := net.IPv4(192, 168, 0, 42)
|
||||||
routeToDstIP, err := RouteGet(dstIP)
|
routeToDstIP, err := RouteGet(dstIP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -48,12 +50,9 @@ func TestRouteAddDel(t *testing.T) {
|
||||||
if len(routeToDstIP) == 0 {
|
if len(routeToDstIP) == 0 {
|
||||||
t.Fatal("Default route not present")
|
t.Fatal("Default route not present")
|
||||||
}
|
}
|
||||||
|
if err := RouteDel(&route); err != nil {
|
||||||
err = RouteDel(&route)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
routes, err = RouteList(link, FAMILY_V4)
|
routes, err = RouteList(link, FAMILY_V4)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -122,25 +121,79 @@ func TestRouteSubscribe(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// add a gateway route
|
// add a gateway route
|
||||||
_, dst, err := net.ParseCIDR("192.168.0.0/24")
|
dst := &net.IPNet{
|
||||||
|
IP: net.IPv4(192, 168, 0, 0),
|
||||||
|
Mask: net.CIDRMask(24, 32),
|
||||||
|
}
|
||||||
|
|
||||||
ip := net.ParseIP("127.1.1.1")
|
ip := net.IPv4(127, 1, 1, 1)
|
||||||
route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
|
route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
|
||||||
err = RouteAdd(&route)
|
if err := RouteAdd(&route); err != nil {
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !expectRouteUpdate(ch, syscall.RTM_NEWROUTE, dst.IP) {
|
if !expectRouteUpdate(ch, syscall.RTM_NEWROUTE, dst.IP) {
|
||||||
t.Fatal("Add update not received as expected")
|
t.Fatal("Add update not received as expected")
|
||||||
}
|
}
|
||||||
|
if err := RouteDel(&route); err != nil {
|
||||||
err = RouteDel(&route)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !expectRouteUpdate(ch, syscall.RTM_DELROUTE, dst.IP) {
|
if !expectRouteUpdate(ch, syscall.RTM_DELROUTE, dst.IP) {
|
||||||
t.Fatal("Del update not received as expected")
|
t.Fatal("Del update not received as expected")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRouteExtraFields(t *testing.T) {
|
||||||
|
tearDown := setUpNetlinkTest(t)
|
||||||
|
defer tearDown()
|
||||||
|
|
||||||
|
// get loopback interface
|
||||||
|
link, err := LinkByName("lo")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
// bring the interface up
|
||||||
|
if err = LinkSetUp(link); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// add a gateway route
|
||||||
|
dst := &net.IPNet{
|
||||||
|
IP: net.IPv4(1, 1, 1, 1),
|
||||||
|
Mask: net.CIDRMask(32, 32),
|
||||||
|
}
|
||||||
|
|
||||||
|
src := net.IPv4(127, 3, 3, 3)
|
||||||
|
route := Route{
|
||||||
|
LinkIndex: link.Attrs().Index,
|
||||||
|
Dst: dst,
|
||||||
|
Src: src,
|
||||||
|
Scope: syscall.RT_SCOPE_LINK,
|
||||||
|
Priority: 13,
|
||||||
|
Table: syscall.RT_TABLE_MAIN,
|
||||||
|
Type: syscall.RTN_UNICAST,
|
||||||
|
}
|
||||||
|
if err := RouteAdd(&route); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
routes, err := RouteList(link, FAMILY_V4)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(routes) != 1 {
|
||||||
|
t.Fatal("Route not added properly")
|
||||||
|
}
|
||||||
|
|
||||||
|
if routes[0].Scope != syscall.RT_SCOPE_LINK {
|
||||||
|
t.Fatal("Invalid Scope. Route not added properly")
|
||||||
|
}
|
||||||
|
if routes[0].Priority != 13 {
|
||||||
|
t.Fatal("Invalid Priority. Route not added properly")
|
||||||
|
}
|
||||||
|
if routes[0].Table != syscall.RT_TABLE_MAIN {
|
||||||
|
t.Fatal("Invalid Scope. Route not added properly")
|
||||||
|
}
|
||||||
|
if routes[0].Type != syscall.RTN_UNICAST {
|
||||||
|
t.Fatal("Invalid Type. Route not added properly")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue