mirror of
https://github.com/vishvananda/netlink.git
synced 2025-09-26 20:01:13 +08:00
Add support for the expires
option of ip route
This commit is contained in:

committed by
Alessandro Boch

parent
cf66e1d224
commit
b032ea08ec
16
route.go
16
route.go
@@ -45,6 +45,17 @@ type Encap interface {
|
||||
Equal(Encap) bool
|
||||
}
|
||||
|
||||
type RouteCacheInfo struct {
|
||||
Users uint32
|
||||
Age uint32
|
||||
Expires int32
|
||||
Error uint32
|
||||
Used uint32
|
||||
Id uint32
|
||||
Ts uint32
|
||||
Tsage uint32
|
||||
}
|
||||
|
||||
// Protocol describe what was the originator of the route
|
||||
type RouteProtocol int
|
||||
|
||||
@@ -87,6 +98,8 @@ type Route struct {
|
||||
QuickACK int
|
||||
Congctl string
|
||||
FastOpenNoCookie int
|
||||
Expires int
|
||||
CacheInfo *RouteCacheInfo
|
||||
}
|
||||
|
||||
func (r Route) String() string {
|
||||
@@ -117,6 +130,9 @@ 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))
|
||||
if r.Expires != 0 {
|
||||
elems = append(elems, fmt.Sprintf("Expires: %dsec", r.Expires))
|
||||
}
|
||||
return fmt.Sprintf("{%s}", strings.Join(elems, " "))
|
||||
}
|
||||
|
||||
|
@@ -1086,6 +1086,12 @@ func (h *Handle) prepareRouteReq(route *Route, req *nl.NetlinkRequest, msg *nl.R
|
||||
msg.Type = uint8(route.Type)
|
||||
}
|
||||
|
||||
if route.Expires > 0 {
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(route.Expires))
|
||||
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_EXPIRES, b))
|
||||
}
|
||||
|
||||
var metrics []*nl.RtAttr
|
||||
if route.MTU > 0 {
|
||||
b := nl.Uint32Attr(uint32(route.MTU))
|
||||
@@ -1320,6 +1326,25 @@ func (h *Handle) RouteListFilteredIter(family int, filter *Route, filterMask uin
|
||||
return executeErr
|
||||
}
|
||||
|
||||
// deserializeRouteCacheInfo decodes a RTA_CACHEINFO attribute into a RouteCacheInfo struct
|
||||
func deserializeRouteCacheInfo(b []byte) (*RouteCacheInfo, error) {
|
||||
if len(b) != 32 {
|
||||
return nil, unix.EINVAL
|
||||
}
|
||||
|
||||
e := nl.NativeEndian()
|
||||
return &RouteCacheInfo{
|
||||
e.Uint32(b),
|
||||
e.Uint32(b[4:]),
|
||||
int32(e.Uint32(b[8:])),
|
||||
e.Uint32(b[12:]),
|
||||
e.Uint32(b[16:]),
|
||||
e.Uint32(b[20:]),
|
||||
e.Uint32(b[24:]),
|
||||
e.Uint32(b[28:]),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// deserializeRoute decodes a binary netlink message into a Route struct
|
||||
func deserializeRoute(m []byte) (Route, error) {
|
||||
msg := nl.DeserializeRtMsg(m)
|
||||
@@ -1363,6 +1388,12 @@ 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_CACHEINFO:
|
||||
route.CacheInfo, err = deserializeRouteCacheInfo(attr.Value)
|
||||
if err != nil {
|
||||
return route, err
|
||||
}
|
||||
route.Expires = int(route.CacheInfo.Expires) / 100
|
||||
case unix.RTA_FLOW:
|
||||
route.Realm = int(native.Uint32(attr.Value[0:4]))
|
||||
case unix.RTA_TABLE:
|
||||
|
@@ -190,7 +190,7 @@ func TestRoute6AddDel(t *testing.T) {
|
||||
IP: net.ParseIP("2001:db8::0"),
|
||||
Mask: net.CIDRMask(64, 128),
|
||||
}
|
||||
route := Route{LinkIndex: link.Attrs().Index, Dst: dst}
|
||||
route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Expires: 10}
|
||||
if err := RouteAdd(&route); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -202,6 +202,25 @@ func TestRoute6AddDel(t *testing.T) {
|
||||
t.Fatal("Route not added properly")
|
||||
}
|
||||
|
||||
// route expiry is supported by kernel 4.4+
|
||||
k, m, err := KernelVersion()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if k > 4 || (k == 4 && m > 4) {
|
||||
foundExpires := false
|
||||
for _, route := range routes {
|
||||
if route.Dst.IP.Equal(dst.IP) {
|
||||
if route.Expires > 0 && route.Expires <= 10 {
|
||||
foundExpires = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if !foundExpires {
|
||||
t.Fatal("Route 'expires' not set")
|
||||
}
|
||||
}
|
||||
|
||||
dstIP := net.ParseIP("2001:db8::1")
|
||||
routeToDstIP, err := RouteGet(dstIP)
|
||||
if err != nil {
|
||||
|
Reference in New Issue
Block a user