mirror of https://github.com/vishvananda/netlink
Add linux route get oif option.
This option is equivalent to "ip route get ... dev ...", which is useful when the route is multipath. Signed-off-by: yuwenchao <yuwenchao@qiyi.com>
This commit is contained in:
parent
533d417a1a
commit
f055e5464f
|
@ -1308,6 +1308,7 @@ func deserializeRoute(m []byte) (Route, error) {
|
|||
// RouteGetWithOptions
|
||||
type RouteGetOptions struct {
|
||||
Iif string
|
||||
Oif string
|
||||
VrfName string
|
||||
SrcAddr net.IP
|
||||
}
|
||||
|
@ -1374,6 +1375,18 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption
|
|||
req.AddData(nl.NewRtAttr(unix.RTA_IIF, b))
|
||||
}
|
||||
|
||||
if len(options.Oif) > 0 {
|
||||
link, err := LinkByName(options.Oif)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(link.Attrs().Index))
|
||||
|
||||
req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
|
||||
}
|
||||
|
||||
if options.SrcAddr != nil {
|
||||
var srcAddr []byte
|
||||
if family == FAMILY_V4 {
|
||||
|
|
|
@ -745,6 +745,98 @@ func TestRouteMultiPath(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestRouteOifOption(t *testing.T) {
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
|
||||
// setup two interfaces: eth0, eth1
|
||||
err := LinkAdd(&Dummy{LinkAttrs{Name: "eth0"}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
link1, err := LinkByName("eth0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err = LinkSetUp(link1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err = LinkAdd(&Dummy{LinkAttrs{Name: "eth1"}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
link2, err := LinkByName("eth1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err = LinkSetUp(link2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// config ip addresses on interfaces
|
||||
addr1 := &Addr{
|
||||
IPNet: &net.IPNet{
|
||||
IP: net.IPv4(192, 168, 1, 1),
|
||||
Mask: net.CIDRMask(24, 32),
|
||||
},
|
||||
}
|
||||
|
||||
if err = AddrAdd(link1, addr1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
addr2 := &Addr{
|
||||
IPNet: &net.IPNet{
|
||||
IP: net.IPv4(192, 168, 2, 1),
|
||||
Mask: net.CIDRMask(24, 32),
|
||||
},
|
||||
}
|
||||
|
||||
if err = AddrAdd(link2, addr2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// add default multipath route
|
||||
dst := &net.IPNet{
|
||||
IP: net.IPv4(0, 0, 0, 0),
|
||||
Mask: net.CIDRMask(0, 32),
|
||||
}
|
||||
gw1 := net.IPv4(192, 168, 1, 254)
|
||||
gw2 := net.IPv4(192, 168, 2, 254)
|
||||
route := Route{Dst: dst, MultiPath: []*NexthopInfo{{LinkIndex: link1.Attrs().Index,
|
||||
Gw: gw1}, {LinkIndex: link2.Attrs().Index, Gw: gw2}}}
|
||||
if err := RouteAdd(&route); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// check getting route from specified Oif
|
||||
dstIP := net.IPv4(10, 1, 1, 1)
|
||||
routes, err := RouteGetWithOptions(dstIP, &RouteGetOptions{Oif: "eth0"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(routes) != 1 || routes[0].LinkIndex != link1.Attrs().Index ||
|
||||
!routes[0].Gw.Equal(gw1) {
|
||||
t.Fatal("Get route from unmatched interface")
|
||||
}
|
||||
|
||||
routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{Oif: "eth1"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(routes) != 1 || routes[0].LinkIndex != link2.Attrs().Index ||
|
||||
!routes[0].Gw.Equal(gw2) {
|
||||
t.Fatal("Get route from unmatched interface")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestFilterDefaultRoute(t *testing.T) {
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
|
|
Loading…
Reference in New Issue