Parse rta_cacheinfo structure in RtNetlinkRouteMessage.

Bug: 183601771
Test: atest NetworkStaticLibTests
Change-Id: I9ea55ad297f5183853eeaa2e53f2406d79a90a20
diff --git a/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkRouteMessage.java b/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkRouteMessage.java
index 1705f1c..9acac69 100644
--- a/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkRouteMessage.java
+++ b/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkRouteMessage.java
@@ -51,6 +51,7 @@
     public static final short RTA_DST           = 1;
     public static final short RTA_OIF           = 4;
     public static final short RTA_GATEWAY       = 5;
+    public static final short RTA_CACHEINFO     = 12;
 
     private int mIfindex;
     @NonNull
@@ -59,6 +60,8 @@
     private IpPrefix mDestination;
     @Nullable
     private InetAddress mGateway;
+    @Nullable
+    private StructRtaCacheInfo mRtaCacheInfo;
 
     private RtNetlinkRouteMessage(StructNlMsgHdr header) {
         super(header);
@@ -66,6 +69,7 @@
         mDestination = null;
         mGateway = null;
         mIfindex = 0;
+        mRtaCacheInfo = null;
     }
 
     public int getInterfaceIndex() {
@@ -87,6 +91,11 @@
         return mGateway;
     }
 
+    @Nullable
+    public StructRtaCacheInfo getRtaCacheInfo() {
+        return mRtaCacheInfo;
+    }
+
     /**
      * Check whether the address families of destination and gateway match rtm_family in
      * StructRtmsg.
@@ -158,6 +167,13 @@
             routeMsg.mIfindex = nlAttr.getValueAsInt(0 /* 0 isn't a valid ifindex */);
         }
 
+        // RTA_CACHEINFO
+        byteBuffer.position(baseOffset);
+        nlAttr = StructNlAttr.findNextAttrOfType(RTA_CACHEINFO, byteBuffer);
+        if (nlAttr != null) {
+            routeMsg.mRtaCacheInfo = StructRtaCacheInfo.parse(nlAttr.getValueAsByteBuffer());
+        }
+
         return routeMsg;
     }
 
@@ -180,6 +196,11 @@
             final StructNlAttr ifindex = new StructNlAttr(RTA_OIF, mIfindex);
             ifindex.pack(byteBuffer);
         }
+        if (mRtaCacheInfo != null) {
+            final StructNlAttr cacheInfo = new StructNlAttr(RTA_CACHEINFO,
+                    mRtaCacheInfo.writeToBytes());
+            cacheInfo.pack(byteBuffer);
+        }
     }
 
     @Override
@@ -189,7 +210,8 @@
                 + "Rtmsg{" + mRtmsg.toString() + "}, "
                 + "destination{" + mDestination.getAddress().getHostAddress() + "}, "
                 + "gateway{" + (mGateway == null ? "" : mGateway.getHostAddress()) + "}, "
-                + "ifindex{" + mIfindex + "} "
+                + "ifindex{" + mIfindex + "}, "
+                + "rta_cacheinfo{" + (mRtaCacheInfo == null ? "" : mRtaCacheInfo.toString()) + "} "
                 + "}";
     }
 }
diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/netlink/RtNetlinkRouteMessageTest.java b/staticlibs/tests/unit/src/com/android/net/module/util/netlink/RtNetlinkRouteMessageTest.java
index 55cfd50..9881653 100644
--- a/staticlibs/tests/unit/src/com/android/net/module/util/netlink/RtNetlinkRouteMessageTest.java
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/netlink/RtNetlinkRouteMessageTest.java
@@ -87,6 +87,8 @@
         assertEquals(routeMsg.getDestination(), TEST_IPV6_GLOBAL_PREFIX);
         assertEquals(735, routeMsg.getInterfaceIndex());
         assertEquals((Inet6Address) routeMsg.getGateway(), TEST_IPV6_LINK_LOCAL_GATEWAY);
+
+        assertNotNull(routeMsg.getRtaCacheInfo());
     }
 
     @Test
@@ -106,7 +108,9 @@
             + "0A400000FC02000100000000"                   // struct rtmsg
             + "1400010020010DB8000100000000000000000000"   // RTA_DST
             + "14000500FE800000000000000000000000000001"   // RTA_GATEWAY
-            + "08000400DF020000";                          // RTA_OIF
+            + "08000400DF020000"                           // RTA_OIF
+            + "24000C0000000000000000005EEA000000000000"   // RTA_CACHEINFO
+            + "00000000000000000000000000000000";
 
     @Test
     public void testPackRtmNewRoute() {
@@ -117,7 +121,7 @@
         assertTrue(msg instanceof RtNetlinkRouteMessage);
         final RtNetlinkRouteMessage routeMsg = (RtNetlinkRouteMessage) msg;
 
-        final ByteBuffer packBuffer = ByteBuffer.allocate(76);
+        final ByteBuffer packBuffer = ByteBuffer.allocate(112);
         packBuffer.order(ByteOrder.LITTLE_ENDIAN);  // For testing.
         routeMsg.pack(packBuffer);
         assertEquals(RTM_NEWROUTE_PACK_HEX, HexDump.toHexString(packBuffer.array()));
@@ -216,7 +220,9 @@
                 + "scope: 0, type: 1, flags: 0}, "
                 + "destination{2001:db8:1::}, "
                 + "gateway{fe80::1}, "
-                + "ifindex{735} "
+                + "ifindex{735}, "
+                + "rta_cacheinfo{clntref: 0, lastuse: 0, expires: 59998, error: 0, used: 0, "
+                + "id: 0, ts: 0, tsage: 0} "
                 + "}";
         assertEquals(expected, routeMsg.toString());
     }