summaryrefslogtreecommitdiffstats
path: root/pimd/pim6_mld_protocol.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-09 13:16:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-09 13:16:35 +0000
commite2bbf175a2184bd76f6c54ccf8456babeb1a46fc (patch)
treef0b76550d6e6f500ada964a3a4ee933a45e5a6f1 /pimd/pim6_mld_protocol.h
parentInitial commit. (diff)
downloadfrr-e2bbf175a2184bd76f6c54ccf8456babeb1a46fc.tar.xz
frr-e2bbf175a2184bd76f6c54ccf8456babeb1a46fc.zip
Adding upstream version 9.1.upstream/9.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'pimd/pim6_mld_protocol.h')
-rw-r--r--pimd/pim6_mld_protocol.h112
1 files changed, 112 insertions, 0 deletions
diff --git a/pimd/pim6_mld_protocol.h b/pimd/pim6_mld_protocol.h
new file mode 100644
index 0000000..08d7871
--- /dev/null
+++ b/pimd/pim6_mld_protocol.h
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * MLD protocol definitions
+ * Copyright (C) 2022 David Lamparter for NetDEF, Inc.
+ */
+
+#ifndef _PIM6_MLD_PROTOCOL_H
+#define _PIM6_MLD_PROTOCOL_H
+
+#include <stdalign.h>
+#include <stdint.h>
+
+/* There is a struct icmp6_hdr provided by OS, but it includes 4 bytes of data.
+ * Not helpful for us if we want to put the MLD struct after it.
+ */
+
+struct icmp6_plain_hdr {
+ uint8_t icmp6_type;
+ uint8_t icmp6_code;
+ uint16_t icmp6_cksum;
+};
+static_assert(sizeof(struct icmp6_plain_hdr) == 4, "struct mismatch");
+static_assert(alignof(struct icmp6_plain_hdr) <= 4, "struct mismatch");
+
+/* for MLDv1 query, report and leave all use the same packet format */
+struct mld_v1_pkt {
+ uint16_t max_resp_code;
+ uint16_t rsvd0;
+ struct in6_addr grp;
+};
+static_assert(sizeof(struct mld_v1_pkt) == 20, "struct mismatch");
+static_assert(alignof(struct mld_v1_pkt) <= 4, "struct mismatch");
+
+
+struct mld_v2_query_hdr {
+ uint16_t max_resp_code;
+ uint16_t rsvd0;
+ struct in6_addr grp;
+ uint8_t flags;
+ uint8_t qqic;
+ uint16_t n_src;
+ struct in6_addr srcs[0];
+};
+static_assert(sizeof(struct mld_v2_query_hdr) == 24, "struct mismatch");
+static_assert(alignof(struct mld_v2_query_hdr) <= 4, "struct mismatch");
+
+
+struct mld_v2_report_hdr {
+ uint16_t rsvd;
+ uint16_t n_records;
+};
+static_assert(sizeof(struct mld_v2_report_hdr) == 4, "struct mismatch");
+static_assert(alignof(struct mld_v2_report_hdr) <= 4, "struct mismatch");
+
+
+struct mld_v2_rec_hdr {
+ uint8_t type;
+ uint8_t aux_len;
+ uint16_t n_src;
+ struct in6_addr grp;
+ struct in6_addr srcs[0];
+};
+static_assert(sizeof(struct mld_v2_rec_hdr) == 20, "struct mismatch");
+static_assert(alignof(struct mld_v2_rec_hdr) <= 4, "struct mismatch");
+
+/* clang-format off */
+enum icmp6_mld_type {
+ ICMP6_MLD_QUERY = 130,
+ ICMP6_MLD_V1_REPORT = 131,
+ ICMP6_MLD_V1_DONE = 132,
+ ICMP6_MLD_V2_REPORT = 143,
+};
+
+enum mld_v2_rec_type {
+ MLD_RECTYPE_IS_INCLUDE = 1,
+ MLD_RECTYPE_IS_EXCLUDE = 2,
+ MLD_RECTYPE_CHANGE_TO_INCLUDE = 3,
+ MLD_RECTYPE_CHANGE_TO_EXCLUDE = 4,
+ MLD_RECTYPE_ALLOW_NEW_SOURCES = 5,
+ MLD_RECTYPE_BLOCK_OLD_SOURCES = 6,
+};
+/* clang-format on */
+
+/* helper functions */
+
+static inline unsigned int mld_max_resp_decode(uint16_t wire)
+{
+ uint16_t code = ntohs(wire);
+ uint8_t exp;
+
+ if (code < 0x8000)
+ return code;
+ exp = (code >> 12) & 0x7;
+ return ((code & 0xfff) | 0x1000) << (exp + 3);
+}
+
+static inline uint16_t mld_max_resp_encode(uint32_t value)
+{
+ uint16_t code;
+ uint8_t exp;
+
+ if (value < 0x8000)
+ code = value;
+ else {
+ exp = 16 - __builtin_clz(value);
+ code = (value >> (exp + 3)) & 0xfff;
+ code |= 0x8000 | (exp << 12);
+ }
+ return htons(code);
+}
+
+#endif /* _PIM6_MLD_PROTOCOL_H */