#define IGMP_HOST_LEAVE_MESSAGE 0x17
#define IGMPV3_HOST_MEMBERSHIP_REPORT 0x22 /* V3 version of 0x12 */
+/*
+ * IGMPv3 and MLDv2 use the same codes.
+ */
#define IGMPV3_MODE_IS_INCLUDE 1
#define IGMPV3_MODE_IS_EXCLUDE 2
#define IGMPV3_CHANGE_TO_INCLUDE_MODE 3
};
BUILD_ASSERT_DECL(ND_MSG_LEN == sizeof(struct ovs_nd_msg));
+/*
+ * Use the same struct for MLD and MLD2, naming members as the defined fields in
+ * in the corresponding version of the protocol, though they are reserved in the
+ * other one.
+ */
+#define MLD_HEADER_LEN 8
+struct mld_header {
+ uint8_t type;
+ uint8_t code;
+ ovs_be16 csum;
+ ovs_be16 mrd;
+ ovs_be16 ngrp;
+};
+BUILD_ASSERT_DECL(MLD_HEADER_LEN == sizeof(struct mld_header));
+
+#define MLD2_RECORD_LEN 20
+struct mld2_record {
+ uint8_t type;
+ uint8_t aux_len;
+ ovs_be16 nsrcs;
+ union ovs_16aligned_in6_addr maddr;
+};
+BUILD_ASSERT_DECL(MLD2_RECORD_LEN == sizeof(struct mld2_record));
+
+#define MLD_QUERY 130
+#define MLD_REPORT 131
+#define MLD_DONE 132
+#define MLD2_REPORT 143
+
/* The IPv6 flow label is in the lower 20 bits of the first 32-bit word. */
#define IPV6_LABEL_MASK 0x000fffff
#define IN6ADDR_EXACT_INIT { { { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, \
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff } } }
+extern const struct in6_addr in6addr_all_hosts;
+#define IN6ADDR_ALL_HOSTS_INIT { { { 0xff,0x02,0x00,0x00,0x00,0x00,0x00,0x00, \
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 } } }
+
static inline bool ipv6_addr_equals(const struct in6_addr *a,
const struct in6_addr *b)
{
return ipv6_addr_equals(mask, &in6addr_exact);
}
+static inline bool ipv6_is_all_hosts(const struct in6_addr *addr) {
+ return ipv6_addr_equals(addr, &in6addr_all_hosts);
+}
+
static inline bool dl_type_is_ip_any(ovs_be16 dl_type)
{
return dl_type == htons(ETH_TYPE_IP)