From 50b4fd79fad57977f286e8a1876e74b8e86d6041 Mon Sep 17 00:00:00 2001
From: Yang Sun <sunytt@google.com>
Date: Sun, 10 Dec 2023 21:55:26 +0800
Subject: [PATCH] Add Mrt6Msg struct for multicast routing support.

Test: atest NetworkStaticLibTests:com.android.net.moduletests.util.structs.StructMrt6MsgTest
Change-Id: I71367761662117aa6c0af3153039e50266d79259
---
 .../module/util/structs/StructMrt6Msg.java    | 52 +++++++++++++++++
 .../util/structs/StructMrt6MsgTest.java       | 58 +++++++++++++++++++
 2 files changed, 110 insertions(+)
 create mode 100644 staticlibs/device/com/android/net/module/util/structs/StructMrt6Msg.java
 create mode 100644 staticlibs/tests/unit/src/com/android/net/module/util/structs/StructMrt6MsgTest.java

diff --git a/staticlibs/device/com/android/net/module/util/structs/StructMrt6Msg.java b/staticlibs/device/com/android/net/module/util/structs/StructMrt6Msg.java
new file mode 100644
index 0000000000..569e3613d8
--- /dev/null
+++ b/staticlibs/device/com/android/net/module/util/structs/StructMrt6Msg.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.net.module.util.structs;
+
+import com.android.net.module.util.Struct;
+import java.net.Inet6Address;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class StructMrt6Msg extends Struct {
+    public static final byte MRT6MSG_NOCACHE = 1;
+
+    @Field(order = 0, type = Type.S8)
+    public final byte mbz;
+    @Field(order = 1, type = Type.S8)
+    public final byte msgType; // message type
+    @Field(order = 2, type = Type.U16, padding = 4)
+    public final int mif; // mif received on
+    @Field(order = 3, type = Type.Ipv6Address)
+    public final Inet6Address src;
+    @Field(order = 4, type = Type.Ipv6Address)
+    public final Inet6Address dst;
+
+    public StructMrt6Msg(final byte mbz, final byte msgType, final int mif,
+                  final Inet6Address source, final Inet6Address destination) {
+        this.mbz = mbz; // kernel should set it to 0
+        this.msgType = msgType;
+        this.mif = mif;
+        this.src = source;
+        this.dst = destination;
+    }
+
+    public static StructMrt6Msg parse(ByteBuffer byteBuffer) {
+        byteBuffer.order(ByteOrder.nativeOrder());
+        return Struct.parse(StructMrt6Msg.class, byteBuffer);
+    }
+}
+
diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/structs/StructMrt6MsgTest.java b/staticlibs/tests/unit/src/com/android/net/module/util/structs/StructMrt6MsgTest.java
new file mode 100644
index 0000000000..f1b75a0a9d
--- /dev/null
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/structs/StructMrt6MsgTest.java
@@ -0,0 +1,58 @@
+package com.android.net.module.util.structs;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.net.InetAddresses;
+import androidx.test.runner.AndroidJUnit4;
+import com.android.net.module.util.Struct;
+
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class StructMrt6MsgTest {
+
+    private static final byte[] MSG_BYTES = new byte[] {
+        0, /* mbz = 0 */
+        1, /* message type = MRT6MSG_NOCACHE */
+        1, 0, /* mif u16 = 1 */
+        0, 0, 0, 0, /* padding */
+        32, 1, 13, -72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* source=2001:db8::1 */
+        -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 52, /* destination=ff05::1234 */
+    };
+
+    private static final Inet6Address SOURCE =
+            (Inet6Address) InetAddresses.parseNumericAddress("2001:db8::1");
+    private static final Inet6Address GROUP =
+            (Inet6Address) InetAddresses.parseNumericAddress("ff05::1234");
+
+    @Test
+    public void testParseMrt6Msg() {
+        final ByteBuffer buf = ByteBuffer.wrap(MSG_BYTES);
+        StructMrt6Msg mrt6Msg = StructMrt6Msg.parse(buf);
+
+        assertEquals(1, mrt6Msg.mif);
+        assertEquals(StructMrt6Msg.MRT6MSG_NOCACHE, mrt6Msg.msgType);
+        assertEquals(SOURCE, mrt6Msg.src);
+        assertEquals(GROUP, mrt6Msg.dst);
+    }
+
+    @Test
+    public void testWriteToBytes() {
+        StructMrt6Msg msg = new StructMrt6Msg((byte) 0 /* mbz must be 0 */,
+                StructMrt6Msg.MRT6MSG_NOCACHE,
+                1 /* mif */,
+                SOURCE,
+                GROUP);
+        byte[] bytes = msg.writeToBytes();
+
+        assertArrayEquals(MSG_BYTES, bytes);
+    }
+}
-- 
GitLab