Repository: antrea-io/antrea
Pull request #3807 (2022-05-18 11:34:15)

[multicast] fix the issue multicast does not work if antreaPolicy is disabled
Currently, packetIn reason only supports 0 and 1. There is no more available packetIn reasons
as traceflow and antreaPolicy use both. Multicast reuses packetIn reason with antreaPolicy, and
uses different register bit to indicate the real reason. There is no queue for packetIn reason
'PacketInReasonNP' if antreaPloicy is disabled. And multicast will not work then.

This patch fixes https://github.com/antrea-io/antrea/issues/3808

wenyingd: In the commit message, Multicast doesn't use a different register, but use a different register bit to mark the packet is for Multicast purpose.
codecov-commenter: # [Codecov](https://codecov.io/gh/antrea-io/antrea/pull/3807?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) Report
> Merging [#3807](https://codecov.io/gh/antrea-io/antrea/pull/3807?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (81f1b6a) into [main](https://codecov.io/gh/antrea-io/antrea/commit/3a51abe9562aad96a8bd486d6fd90f679c8cced6?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (3a51abe) will **decrease** coverage by `25.16%`.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/antrea-io/antrea/pull/3807/graphs/tree.svg?width=650&height=150&src=pr&token=TjWaLL2GoC&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None)](https://codecov.io/gh/antrea-io/antrea/pull/3807?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None)

```diff
@@             Coverage Diff             @@
##             main    #3807       +/-   ##
===========================================
- Coverage   63.38%   38.22%   -25.17%     
===========================================
  Files         280      114      -166     
  Lines       39750    15684    -24066     
===========================================
- Hits        25197     5995    -19202     
+ Misses      12593     9210     -3383     
+ Partials     1960      479     -1481     
```

| Flag | Coverage Δ | |
|---|---|---|
| integration-tests | `38.22% <ø> (?)` | |
| kind-e2e-tests | `?` | |
| unit-tests | `?` | |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/antrea-io/antrea/pull/3807?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) | Coverage Δ | |
|---|---|---|
| [pkg/controller/metrics/prometheus.go](https://codecov.io/gh/antrea-io/antrea/pull/3807/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2NvbnRyb2xsZXIvbWV0cmljcy9wcm9tZXRoZXVzLmdv) | | |
| [pkg/signals/signals.go](https://codecov.io/gh/antrea-io/antrea/pull/3807/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL3NpZ25hbHMvc2lnbmFscy5nbw==) | | |
| [pkg/agent/openflow/framework.go](https://codecov.io/gh/antrea-io/antrea/pull/3807/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2FnZW50L29wZW5mbG93L2ZyYW1ld29yay5nbw==) | | |
| [pkg/apiserver/storage/ram/watch.go](https://codecov.io/gh/antrea-io/antrea/pull/3807/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2FwaXNlcnZlci9zdG9yYWdlL3JhbS93YXRjaC5nbw==) | | |
| [pkg/ovs/ovsctl/interface.go](https://codecov.io/gh/antrea-io/antrea/pull/3807/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL292cy9vdnNjdGwvaW50ZXJmYWNlLmdv) | | |
| [pkg/agent/openflow/openflow\_test\_utils.go](https://codecov.io/gh/antrea-io/antrea/pull/3807/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2FnZW50L29wZW5mbG93L29wZW5mbG93X3Rlc3RfdXRpbHMuZ28=) | | |
| [.../flowexporter/connections/conntrack\_connections.go](https://codecov.io/gh/antrea-io/antrea/pull/3807/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2FnZW50L2Zsb3dleHBvcnRlci9jb25uZWN0aW9ucy9jb25udHJhY2tfY29ubmVjdGlvbnMuZ28=) | | |
| [...gistry/networkpolicy/networkpolicy/subresources.go](https://codecov.io/gh/antrea-io/antrea/pull/3807/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2FwaXNlcnZlci9yZWdpc3RyeS9uZXR3b3JrcG9saWN5L25ldHdvcmtwb2xpY3kvc3VicmVzb3VyY2VzLmdv) | | |
| [...gregator/apiserver/handlers/flowrecords/handler.go](https://codecov.io/gh/antrea-io/antrea/pull/3807/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2Zsb3dhZ2dyZWdhdG9yL2FwaXNlcnZlci9oYW5kbGVycy9mbG93cmVjb3Jkcy9oYW5kbGVyLmdv) | | |
| [pkg/apis/system/install/install.go](https://codecov.io/gh/antrea-io/antrea/pull/3807/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2FwaXMvc3lzdGVtL2luc3RhbGwvaW5zdGFsbC5nbw==) | | |
| ... and [384 more](https://codecov.io/gh/antrea-io/antrea/pull/3807/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) | |

tnqn: /test-all

Patch:
diff --git a/cmd/antrea-agent/agent.go b/cmd/antrea-agent/agent.go
index 95898e1b5..4dffbb769 100644
--- a/cmd/antrea-agent/agent.go
+++ b/cmd/antrea-agent/agent.go
@@ -633,17 +633,8 @@ func run(o *Options) error {
 	}
 	go apiServer.Run(stopCh)
 
-	// Start PacketIn for features and specify their own reason.
-	var packetInReasons []uint8
-	if features.DefaultFeatureGate.Enabled(features.Traceflow) {
-		packetInReasons = append(packetInReasons, uint8(openflow.PacketInReasonTF))
-	}
-	if features.DefaultFeatureGate.Enabled(features.AntreaPolicy) {
-		packetInReasons = append(packetInReasons, uint8(openflow.PacketInReasonNP))
-	}
-	if len(packetInReasons) > 0 {
-		go ofClient.StartPacketInHandler(packetInReasons, stopCh)
-	}
+	// Start PacketIn
+	go ofClient.StartPacketInHandler(stopCh)
 
 	// Start the goroutine to periodically export IPFIX flow records.
 	if features.DefaultFeatureGate.Enabled(features.FlowExporter) {
diff --git a/pkg/agent/openflow/client.go b/pkg/agent/openflow/client.go
index 28980801b..265bded82 100644
--- a/pkg/agent/openflow/client.go
+++ b/pkg/agent/openflow/client.go
@@ -215,7 +215,7 @@ type Client interface {
 	// packets through registered handlers.
 	RegisterPacketInHandler(packetHandlerReason uint8, packetHandlerName string, packetInHandler interface{})
 
-	StartPacketInHandler(packetInStartedReason []uint8, stopCh <-chan struct{})
+	StartPacketInHandler(stopCh <-chan struct{})
 	// Get traffic metrics of each NetworkPolicy rule.
 	NetworkPolicyMetrics() map[uint32]*types.RuleMetric
 	// SendTCPPacketOut sends TCP packet as a packet-out to OVS.
diff --git a/pkg/agent/openflow/packetin.go b/pkg/agent/openflow/packetin.go
index b51e534ac..353610abd 100644
--- a/pkg/agent/openflow/packetin.go
+++ b/pkg/agent/openflow/packetin.go
@@ -84,13 +84,13 @@ func newfeatureStartPacketIn(reason uint8, stopCh <-chan struct{}) *featureStart
 }
 
 // StartPacketInHandler is the starting point for processing feature packetin requests.
-func (c *client) StartPacketInHandler(packetInStartedReason []uint8, stopCh <-chan struct{}) {
-	if len(c.packetInHandlers) == 0 || len(packetInStartedReason) == 0 {
+func (c *client) StartPacketInHandler(stopCh <-chan struct{}) {
+	if len(c.packetInHandlers) == 0 {
 		return
 	}
 
 	// Iterate through each feature that starts packetin. Subscribe with their specified reason.
-	for _, reason := range packetInStartedReason {
+	for reason := range c.packetInHandlers {
 		featurePacketIn := newfeatureStartPacketIn(reason, stopCh)
 		err := c.subscribeFeaturePacketIn(featurePacketIn)
 		if err != nil {
diff --git a/pkg/apis/controlplane/types.go b/pkg/apis/controlplane/types.go
index 198ee9c89..68920081d 100644
--- a/pkg/apis/controlplane/types.go
+++ b/pkg/apis/controlplane/types.go
@@ -340,6 +340,16 @@ type NodeStatsSummary struct {
 	AntreaClusterNetworkPolicies []NetworkPolicyStats
 	// The TrafficStats of Antrea NetworkPolicies collected from the Node.
 	AntreaNetworkPolicies []NetworkPolicyStats
+	// Multicast group information from the Node.
+	Multicast []MulticastGroupInfo
+}
+
+// MulticastGroupInfo contains the list of Pods that have joined a multicast group, for a given Node.
+type MulticastGroupInfo struct {
+	// Group is the IP of the multicast group.
+	Group string
+	// Pods is the list of Pods that have joined the multicast group.
+	Pods []PodReference
 }
 
 // NetworkPolicyStats contains the information and traffic stats of a NetworkPolicy.
diff --git a/pkg/apis/controlplane/v1beta2/generated.pb.go b/pkg/apis/controlplane/v1beta2/generated.pb.go
index e918449e2..c02582c10 100644
--- a/pkg/apis/controlplane/v1beta2/generated.pb.go
+++ b/pkg/apis/controlplane/v1beta2/generated.pb.go
@@ -495,10 +495,38 @@ func (m *IPNet) XXX_DiscardUnknown() {
 
 var xxx_messageInfo_IPNet proto.InternalMessageInfo
 
+func (m *MulticastGroupInfo) Reset()      { *m = MulticastGroupInfo{} }
+func (*MulticastGroupInfo) ProtoMessage() {}
+func (*MulticastGroupInfo) Descriptor() ([]byte, []int) {
+	return fileDescriptor_fbaa7d016762fa1d, []int{16}
+}
+func (m *MulticastGroupInfo) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *MulticastGroupInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *MulticastGroupInfo) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_MulticastGroupInfo.Merge(m, src)
+}
+func (m *MulticastGroupInfo) XXX_Size() int {
+	return m.Size()
+}
+func (m *MulticastGroupInfo) XXX_DiscardUnknown() {
+	xxx_messageInfo_MulticastGroupInfo.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MulticastGroupInfo proto.InternalMessageInfo
+
 func (m *NamedPort) Reset()      { *m = NamedPort{} }
 func (*NamedPort) ProtoMessage() {}
 func (*NamedPort) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fbaa7d016762fa1d, []int{16}
+	return fileDescriptor_fbaa7d016762fa1d, []int{17}
 }
 func (m *NamedPort) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -526,7 +554,7 @@ var xxx_messageInfo_NamedPort proto.InternalMessageInfo
 func (m *NetworkPolicy) Reset()      { *m = NetworkPolicy{} }
 func (*NetworkPolicy) ProtoMessage() {}
 func (*NetworkPolicy) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fbaa7d016762fa1d, []int{17}
+	return fileDescriptor_fbaa7d016762fa1d, []int{18}
 }
 func (m *NetworkPolicy) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -554,7 +582,7 @@ var xxx_messageInfo_NetworkPolicy proto.InternalMessageInfo
 func (m *NetworkPolicyList) Reset()      { *m = NetworkPolicyList{} }
 func (*NetworkPolicyList) ProtoMessage() {}
 func (*NetworkPolicyList) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fbaa7d016762fa1d, []int{18}
+	return fileDescriptor_fbaa7d016762fa1d, []int{19}
 }
 func (m *NetworkPolicyList) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -582,7 +610,7 @@ var xxx_messageInfo_NetworkPolicyList proto.InternalMessageInfo
 func (m *NetworkPolicyNodeStatus) Reset()      { *m = NetworkPolicyNodeStatus{} }
 func (*NetworkPolicyNodeStatus) ProtoMessage() {}
 func (*NetworkPolicyNodeStatus) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fbaa7d016762fa1d, []int{19}
+	return fileDescriptor_fbaa7d016762fa1d, []int{20}
 }
 func (m *NetworkPolicyNodeStatus) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -610,7 +638,7 @@ var xxx_messageInfo_NetworkPolicyNodeStatus proto.InternalMessageInfo
 func (m *NetworkPolicyPeer) Reset()      { *m = NetworkPolicyPeer{} }
 func (*NetworkPolicyPeer) ProtoMessage() {}
 func (*NetworkPolicyPeer) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fbaa7d016762fa1d, []int{20}
+	return fileDescriptor_fbaa7d016762fa1d, []int{21}
 }
 func (m *NetworkPolicyPeer) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -638,7 +666,7 @@ var xxx_messageInfo_NetworkPolicyPeer proto.InternalMessageInfo
 func (m *NetworkPolicyReference) Reset()      { *m = NetworkPolicyReference{} }
 func (*NetworkPolicyReference) ProtoMessage() {}
 func (*NetworkPolicyReference) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fbaa7d016762fa1d, []int{21}
+	return fileDescriptor_fbaa7d016762fa1d, []int{22}
 }
 func (m *NetworkPolicyReference) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -666,7 +694,7 @@ var xxx_messageInfo_NetworkPolicyReference proto.InternalMessageInfo
 func (m *NetworkPolicyRule) Reset()      { *m = NetworkPolicyRule{} }
 func (*NetworkPolicyRule) ProtoMessage() {}
 func (*NetworkPolicyRule) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fbaa7d016762fa1d, []int{22}
+	return fileDescriptor_fbaa7d016762fa1d, []int{23}
 }
 func (m *NetworkPolicyRule) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -694,7 +722,7 @@ var xxx_messageInfo_NetworkPolicyRule proto.InternalMessageInfo
 func (m *NetworkPolicyStats) Reset()      { *m = NetworkPolicyStats{} }
 func (*NetworkPolicyStats) ProtoMessage() {}
 func (*NetworkPolicyStats) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fbaa7d016762fa1d, []int{23}
+	return fileDescriptor_fbaa7d016762fa1d, []int{24}
 }
 func (m *NetworkPolicyStats) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -722,7 +750,7 @@ var xxx_messageInfo_NetworkPolicyStats proto.InternalMessageInfo
 func (m *NetworkPolicyStatus) Reset()      { *m = NetworkPolicyStatus{} }
 func (*NetworkPolicyStatus) ProtoMessage() {}
 func (*NetworkPolicyStatus) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fbaa7d016762fa1d, []int{24}
+	return fileDescriptor_fbaa7d016762fa1d, []int{25}
 }
 func (m *NetworkPolicyStatus) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -750,7 +778,7 @@ var xxx_messageInfo_NetworkPolicyStatus proto.InternalMessageInfo
 func (m *NodeReference) Reset()      { *m = NodeReference{} }
 func (*NodeReference) ProtoMessage() {}
 func (*NodeReference) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fbaa7d016762fa1d, []int{25}
+	return fileDescriptor_fbaa7d016762fa1d, []int{26}
 }
 func (m *NodeReference) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -778,7 +806,7 @@ var xxx_messageInfo_NodeReference proto.InternalMessageInfo
 func (m *NodeStatsSummary) Reset()      { *m = NodeStatsSummary{} }
 func (*NodeStatsSummary) ProtoMessage() {}
 func (*NodeStatsSummary) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fbaa7d016762fa1d, []int{26}
+	return fileDescriptor_fbaa7d016762fa1d, []int{27}
 }
 func (m *NodeStatsSummary) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -806,7 +834,7 @@ var xxx_messageInfo_NodeStatsSummary proto.InternalMessageInfo
 func (m *PaginationGetOptions) Reset()      { *m = PaginationGetOptions{} }
 func (*PaginationGetOptions) ProtoMessage() {}
 func (*PaginationGetOptions) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fbaa7d016762fa1d, []int{27}
+	return fileDescriptor_fbaa7d016762fa1d, []int{28}
 }
 func (m *PaginationGetOptions) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -834,7 +862,7 @@ var xxx_messageInfo_PaginationGetOptions proto.InternalMessageInfo
 func (m *PodReference) Reset()      { *m = PodReference{} }
 func (*PodReference) ProtoMessage() {}
 func (*PodReference) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fbaa7d016762fa1d, []int{28}
+	return fileDescriptor_fbaa7d016762fa1d, []int{29}
 }
 func (m *PodReference) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -862,7 +890,7 @@ var xxx_messageInfo_PodReference proto.InternalMessageInfo
 func (m *Service) Reset()      { *m = Service{} }
 func (*Service) ProtoMessage() {}
 func (*Service) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fbaa7d016762fa1d, []int{29}
+	return fileDescriptor_fbaa7d016762fa1d, []int{30}
 }
 func (m *Service) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -890,7 +918,7 @@ var xxx_messageInfo_Service proto.InternalMessageInfo
 func (m *ServiceReference) Reset()      { *m = ServiceReference{} }
 func (*ServiceReference) ProtoMessage() {}
 func (*ServiceReference) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fbaa7d016762fa1d, []int{30}
+	return fileDescriptor_fbaa7d016762fa1d, []int{31}
 }
 func (m *ServiceReference) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -932,6 +960,7 @@ func init() {
 	proto.RegisterType((*GroupReference)(nil), "antrea_io.antrea.pkg.apis.controlplane.v1beta2.GroupReference")
 	proto.RegisterType((*IPBlock)(nil), "antrea_io.antrea.pkg.apis.controlplane.v1beta2.IPBlock")
 	proto.RegisterType((*IPNet)(nil), "antrea_io.antrea.pkg.apis.controlplane.v1beta2.IPNet")
+	proto.RegisterType((*MulticastGroupInfo)(nil), "antrea_io.antrea.pkg.apis.controlplane.v1beta2.MulticastGroupInfo")
 	proto.RegisterType((*NamedPort)(nil), "antrea_io.antrea.pkg.apis.controlplane.v1beta2.NamedPort")
 	proto.RegisterType((*NetworkPolicy)(nil), "antrea_io.antrea.pkg.apis.controlplane.v1beta2.NetworkPolicy")
 	proto.RegisterType((*NetworkPolicyList)(nil), "antrea_io.antrea.pkg.apis.controlplane.v1beta2.NetworkPolicyList")
@@ -954,136 +983,141 @@ func init() {
 }
 
 var fileDescriptor_fbaa7d016762fa1d = []byte{
-	// 2063 bytes of a gzipped FileDescriptorProto
+	// 2132 bytes of a gzipped FileDescriptorProto
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x1a, 0xcd, 0x6f, 0x1b, 0x59,
-	0xbd, 0xe3, 0x8f, 0x26, 0xfe, 0xd9, 0x49, 0x9c, 0x97, 0x2d, 0x35, 0x4b, 0xb1, 0xb3, 0xb3, 0x80,
-	0x72, 0x80, 0xf1, 0x26, 0xb4, 0xdb, 0xc2, 0x6e, 0x17, 0xe2, 0x24, 0x8d, 0x2c, 0xb5, 0xa9, 0x79,
-	0xc9, 0xaa, 0x12, 0x50, 0xd8, 0xc9, 0xcc, 0xb3, 0xf3, 0x88, 0x3d, 0x33, 0xcc, 0x3c, 0x87, 0x46,
-	0x48, 0x68, 0x11, 0x70, 0xd8, 0x05, 0x09, 0x6e, 0x5c, 0xe1, 0xc4, 0x85, 0x7f, 0x82, 0x03, 0x52,
-	0xc5, 0x69, 0x57, 0x08, 0xb1, 0x27, 0x8b, 0x1a, 0x01, 0xe2, 0xc0, 0x3f, 0x10, 0x2e, 0xe8, 0xbd,
-	0x79, 0x33, 0xf3, 0xc6, 0x4e, 0x9a, 0xba, 0x49, 0x83, 0x04, 0x7b, 0xaa, 0xe7, 0xfd, 0xbe, 0xdf,
-	0xef, 0xfb, 0xa5, 0xf0, 0x96, 0xe9, 0x30, 0x9f, 0x98, 0x06, 0x75, 0xeb, 0xe1, 0xaf, 0xba, 0xb7,
-	0xdf, 0xa9, 0x9b, 0x1e, 0x0d, 0xea, 0x96, 0xeb, 0x30, 0xdf, 0xed, 0x7a, 0x5d, 0xd3, 0x21, 0xf5,
-	0x83, 0xe5, 0x5d, 0xc2, 0xcc, 0x95, 0x7a, 0x87, 0x38, 0xc4, 0x37, 0x19, 0xb1, 0x0d, 0xcf, 0x77,
-	0x99, 0x8b, 0x8c, 0x90, 0xea, 0xdb, 0xd4, 0x95, 0xbf, 0x0c, 0x6f, 0xbf, 0x63, 0x70, 0x7a, 0x43,
-	0xa5, 0x37, 0x24, 0xfd, 0xcb, 0xb7, 0x4e, 0x96, 0x17, 0x30, 0x93, 0x05, 0xf5, 0x83, 0x65, 0xb3,
-	0xeb, 0xed, 0x99, 0xcb, 0xa3, 0x92, 0x5e, 0xfe, 0x42, 0x87, 0xb2, 0xbd, 0xfe, 0xae, 0x61, 0xb9,
-	0xbd, 0x7a, 0xc7, 0xed, 0xb8, 0x75, 0x71, 0xbc, 0xdb, 0x6f, 0x8b, 0x2f, 0xf1, 0x21, 0x7e, 0x49,
-	0xf4, 0xeb, 0xfb, 0xb7, 0x02, 0x21, 0xc5, 0xa3, 0x3d, 0xd3, 0xda, 0xa3, 0x0e, 0xf1, 0x0f, 0x13,
-	0x59, 0x3d, 0xc2, 0xcc, 0xfa, 0xc1, 0xb8, 0x90, 0xfa, 0x49, 0x54, 0x7e, 0xdf, 0x61, 0xb4, 0x47,
-	0xc6, 0x08, 0x5e, 0x3f, 0x8d, 0x20, 0xb0, 0xf6, 0x48, 0xcf, 0x1c, 0xa3, 0xfb, 0xe2, 0x49, 0x74,
-	0x7d, 0x46, 0xbb, 0x75, 0xea, 0xb0, 0x80, 0xf9, 0xa3, 0x44, 0xfa, 0x3f, 0x34, 0x28, 0xad, 0xda,
-	0xb6, 0x4f, 0x82, 0x60, 0xd3, 0x77, 0xfb, 0x1e, 0x7a, 0x07, 0xa6, 0xb9, 0x25, 0xb6, 0xc9, 0xcc,
-	0x8a, 0xb6, 0xa8, 0x2d, 0x15, 0x57, 0x5e, 0x33, 0x42, 0xc6, 0x86, 0xca, 0x38, 0xf1, 0x09, 0xc7,
-	0x36, 0x0e, 0x96, 0x8d, 0xfb, 0xbb, 0xdf, 0x21, 0x16, 0xbb, 0x47, 0x98, 0xd9, 0x40, 0x8f, 0x07,
-	0xb5, 0x4b, 0xc3, 0x41, 0x0d, 0x92, 0x33, 0x1c, 0x73, 0x45, 0x7d, 0x28, 0x75, 0xb8, 0xa8, 0x7b,
-	0xa4, 0xb7, 0x4b, 0xfc, 0xa0, 0x92, 0x59, 0xcc, 0x2e, 0x15, 0x57, 0xde, 0x98, 0xd0, 0xed, 0xc6,
-	0x66, 0xc2, 0xa3, 0xf1, 0x92, 0x14, 0x58, 0x52, 0x0e, 0x03, 0x9c, 0x12, 0xa3, 0xff, 0x51, 0x83,
-	0xb2, 0x6a, 0xe9, 0x5d, 0x1a, 0x30, 0xf4, 0xcd, 0x31, 0x6b, 0x8d, 0x67, 0xb3, 0x96, 0x53, 0x0b,
-	0x5b, 0xcb, 0x52, 0xf4, 0x74, 0x74, 0xa2, 0x58, 0x6a, 0x42, 0x9e, 0x32, 0xd2, 0x8b, 0x4c, 0x7c,
-	0x73, 0x52, 0x13, 0x55, 0x75, 0x1b, 0x33, 0x52, 0x50, 0xbe, 0xc9, 0x59, 0xe2, 0x90, 0xb3, 0xfe,
-	0x5e, 0x16, 0xe6, 0x55, 0xb4, 0x96, 0xc9, 0xac, 0xbd, 0x0b, 0x70, 0xe2, 0x8f, 0x35, 0x98, 0x37,
-	0x6d, 0x9b, 0xd8, 0x9b, 0xe7, 0xec, 0xca, 0x4f, 0x4a, 0xb1, 0xdc, 0xaa, 0x34, 0x77, 0x3c, 0x2e,
-	0x10, 0xbd, 0xaf, 0xc1, 0x82, 0x4f, 0x7a, 0xee, 0xc1, 0x88, 0x22, 0xd9, 0xb3, 0x2b, 0xf2, 0x29,
-	0xa9, 0xc8, 0x02, 0x1e, 0xe7, 0x8f, 0x8f, 0x13, 0xaa, 0xff, 0x53, 0x83, 0xd9, 0x55, 0xcf, 0xeb,
-	0x52, 0x62, 0xef, 0xb8, 0xff, 0xe3, 0xd9, 0xf4, 0x67, 0x0d, 0x50, 0xda, 0xd6, 0x0b, 0xc8, 0x27,
-	0x2b, 0x9d, 0x4f, 0x6f, 0x4d, 0x9c, 0x4f, 0x29, 0x85, 0x4f, 0xc8, 0xa8, 0x9f, 0x66, 0x61, 0x21,
-	0x8d, 0xf8, 0x71, 0x4e, 0xfd, 0xf7, 0x72, 0xea, 0x57, 0x39, 0x58, 0x58, 0xeb, 0xf6, 0x03, 0x46,
-	0xfc, 0x94, 0x92, 0x2f, 0xde, 0x1b, 0x3f, 0xd4, 0xa0, 0x4c, 0xda, 0x6d, 0x62, 0x31, 0x7a, 0x40,
-	0xce, 0xd1, 0x19, 0x15, 0x29, 0xb5, 0xbc, 0x31, 0xc2, 0x1c, 0x8f, 0x89, 0x43, 0x3f, 0x80, 0xf9,
-	0xf8, 0xac, 0xd9, 0x6a, 0x74, 0x5d, 0x6b, 0x3f, 0xf2, 0xc3, 0x8d, 0x49, 0x75, 0x68, 0xb6, 0xb6,
-	0x08, 0x4b, 0x42, 0x61, 0x63, 0x94, 0x2f, 0x1e, 0x17, 0x85, 0x6e, 0x41, 0x89, 0xb9, 0xcc, 0xec,
-	0x46, 0xe6, 0xe7, 0x16, 0xb5, 0xa5, 0x6c, 0x52, 0x1f, 0x76, 0x14, 0x18, 0x4e, 0x61, 0xa2, 0x15,
-	0x00, 0xf1, 0xdd, 0x32, 0x3b, 0x24, 0xa8, 0xe4, 0x05, 0x5d, 0x7c, 0xdf, 0x3b, 0x31, 0x04, 0x2b,
-	0x58, 0xe8, 0x06, 0x14, 0xad, 0xbe, 0xef, 0x13, 0x87, 0xf1, 0xef, 0xca, 0x65, 0x41, 0xb4, 0x20,
-	0x89, 0x8a, 0x6b, 0x09, 0x08, 0xab, 0x78, 0xfa, 0xdf, 0x35, 0x28, 0x6e, 0x74, 0xfe, 0x0f, 0x26,
-	0x98, 0x0f, 0x35, 0x98, 0x53, 0x0c, 0xbd, 0x80, 0x82, 0xfb, 0x4e, 0xba, 0xe0, 0x4e, 0x6c, 0xa1,
-	0xa2, 0xed, 0x09, 0xd5, 0xf6, 0x67, 0x59, 0x28, 0x2b, 0x58, 0x61, 0xa9, 0xb5, 0x01, 0xdc, 0xf8,
-	0xde, 0xcf, 0xd5, 0x87, 0x0a, 0xdf, 0x8f, 0xcb, 0xed, 0x31, 0xe5, 0xb6, 0x0b, 0x57, 0x37, 0x1e,
-	0x31, 0xe2, 0x3b, 0x66, 0x77, 0xc3, 0x61, 0x94, 0x1d, 0x62, 0xd2, 0x26, 0x3e, 0x71, 0x2c, 0x82,
-	0x16, 0x21, 0xe7, 0x98, 0x3d, 0x22, 0xdc, 0x51, 0x68, 0x94, 0x24, 0xeb, 0xdc, 0x96, 0xd9, 0x23,
-	0x58, 0x40, 0x50, 0x1d, 0x0a, 0xfc, 0xdf, 0xc0, 0x33, 0x2d, 0x52, 0xc9, 0x08, 0xb4, 0x79, 0x89,
-	0x56, 0xd8, 0x8a, 0x00, 0x38, 0xc1, 0xd1, 0xff, 0xad, 0x41, 0x59, 0x88, 0x5f, 0x0d, 0x02, 0xd7,
-	0xa2, 0x26, 0xa3, 0xae, 0x73, 0x31, 0x7d, 0xb6, 0x6c, 0x4a, 0x89, 0xd2, 0xfe, 0xe7, 0x1e, 0x29,
-	0x04, 0x75, 0x7c, 0x49, 0x49, 0x71, 0x5f, 0x1d, 0xe1, 0x8f, 0xc7, 0x24, 0xea, 0x1f, 0x66, 0xa1,
-	0xa8, 0x5c, 0x3e, 0x7a, 0x00, 0x59, 0xcf, 0xb5, 0xa5, 0xcd, 0x13, 0xef, 0x0a, 0x2d, 0xd7, 0x4e,
-	0xd4, 0x98, 0x1a, 0x0e, 0x6a, 0x59, 0x7e, 0xc2, 0x39, 0xa2, 0x1f, 0x69, 0x30, 0x4b, 0x52, 0x5e,
-	0x15, 0xde, 0x29, 0xae, 0x6c, 0x4e, 0x9c, 0xcf, 0xc7, 0xc7, 0x46, 0x03, 0x0d, 0x07, 0xb5, 0xd9,
-	0x11, 0xe0, 0x88, 0x48, 0xf4, 0x39, 0xc8, 0x52, 0x2f, 0x0c, 0xeb, 0x52, 0xe3, 0x25, 0xae, 0x60,
-	0xb3, 0x15, 0x1c, 0x0d, 0x6a, 0x85, 0x66, 0x4b, 0x2e, 0x30, 0x98, 0x23, 0xa0, 0x6f, 0x41, 0xde,
-	0x73, 0x7d, 0xc6, 0x9b, 0x0d, 0xf7, 0xc8, 0x97, 0x26, 0xd5, 0x91, 0x47, 0x9a, 0xdd, 0x72, 0x7d,
-	0x96, 0x54, 0x1c, 0xfe, 0x15, 0xe0, 0x90, 0x2d, 0xfa, 0x06, 0xe4, 0x1c, 0xd7, 0x26, 0xa2, 0x27,
-	0x15, 0x57, 0x6e, 0x4f, 0xcc, 0xde, 0xb5, 0x49, 0x62, 0xf8, 0xb4, 0x48, 0x01, 0x7e, 0x24, 0x98,
-	0xea, 0xbf, 0xd1, 0x60, 0x36, 0x1d, 0x12, 0xe9, 0xac, 0xd0, 0x4e, 0xcf, 0x8a, 0x38, 0xd1, 0x32,
-	0x27, 0x26, 0x5a, 0x03, 0xb2, 0x7d, 0x6a, 0x57, 0xb2, 0x02, 0xe1, 0x35, 0x89, 0x90, 0x7d, 0xbb,
-	0xb9, 0x7e, 0x34, 0xa8, 0xbd, 0x72, 0xd2, 0x2b, 0x00, 0x3b, 0xf4, 0x48, 0x60, 0xbc, 0xdd, 0x5c,
-	0xc7, 0x9c, 0x58, 0xff, 0x9d, 0x06, 0x53, 0xb2, 0xcf, 0xa3, 0x07, 0x90, 0xb3, 0xa8, 0xed, 0xcb,
-	0xd0, 0x7b, 0xce, 0xc9, 0x22, 0x56, 0x74, 0xad, 0xb9, 0x8e, 0xb1, 0x60, 0x88, 0x1e, 0xc2, 0x65,
-	0xf2, 0xc8, 0x22, 0x1e, 0x93, 0xe9, 0xf5, 0x9c, 0xac, 0x67, 0x25, 0xeb, 0xcb, 0x1b, 0x82, 0x19,
-	0x96, 0x4c, 0xf5, 0x36, 0xe4, 0x05, 0x02, 0x7a, 0x15, 0x32, 0xd4, 0x13, 0xea, 0x97, 0x1a, 0x0b,
-	0xc3, 0x41, 0x2d, 0xd3, 0x6c, 0xa5, 0x23, 0x2b, 0x43, 0x3d, 0x3e, 0xcc, 0x78, 0x3e, 0x69, 0xd3,
-	0x47, 0x77, 0x89, 0xd3, 0x61, 0x7b, 0xe2, 0x7e, 0xf3, 0x49, 0xe3, 0x6d, 0x29, 0x30, 0x9c, 0xc2,
-	0xd4, 0xdf, 0xd3, 0xa0, 0x10, 0x87, 0x15, 0xf7, 0x0f, 0x8f, 0x24, 0x21, 0x2e, 0x9f, 0x98, 0xcd,
-	0x61, 0x58, 0x40, 0x9e, 0xc1, 0x83, 0xb7, 0x60, 0x5a, 0xbc, 0xbf, 0x58, 0x6e, 0x57, 0xba, 0xf1,
-	0x5a, 0xd4, 0x86, 0x5b, 0xf2, 0xfc, 0x48, 0xf9, 0x8d, 0x63, 0x6c, 0xfd, 0x5f, 0x59, 0x98, 0xd9,
-	0x22, 0xec, 0x7b, 0xae, 0xbf, 0xdf, 0x72, 0xbb, 0xd4, 0x3a, 0xbc, 0x80, 0x82, 0xd9, 0x86, 0xbc,
-	0xdf, 0xef, 0x92, 0xa8, 0x48, 0xae, 0x4e, 0x9c, 0x33, 0xaa, 0xbe, 0xb8, 0xdf, 0x25, 0x49, 0x6a,
-	0xf2, 0xaf, 0x00, 0x87, 0xec, 0xd1, 0x6d, 0x98, 0x33, 0x53, 0x9b, 0x57, 0x58, 0x2e, 0x0a, 0xc2,
-	0xa7, 0x73, 0xe9, 0xa5, 0x2c, 0xc0, 0xa3, 0xb8, 0x68, 0x89, 0x5f, 0x2a, 0x75, 0x7d, 0x5e, 0xe0,
-	0xf8, 0xa4, 0xaa, 0x35, 0x4a, 0xe1, 0x85, 0x86, 0x67, 0x38, 0x86, 0xa2, 0xeb, 0x50, 0x62, 0x94,
-	0xf8, 0x11, 0x44, 0xd4, 0x82, 0x7c, 0xa3, 0x2c, 0x66, 0x5a, 0xe5, 0x1c, 0xa7, 0xb0, 0x50, 0x00,
-	0x85, 0xc0, 0xed, 0xfb, 0x16, 0xcf, 0x7f, 0x31, 0x9d, 0x16, 0x57, 0xee, 0x9c, 0xed, 0x2a, 0xe2,
-	0x3a, 0x32, 0xc3, 0xab, 0xc1, 0x76, 0xc4, 0x1c, 0x27, 0x72, 0xf4, 0x3f, 0x69, 0x30, 0x9f, 0x22,
-	0xba, 0x80, 0xb1, 0x6f, 0x37, 0x3d, 0xf6, 0xdd, 0x3e, 0x93, 0x91, 0x27, 0x0c, 0x7e, 0xdf, 0x87,
-	0xab, 0x29, 0x34, 0x5e, 0x44, 0xb7, 0x99, 0xc9, 0xfa, 0x01, 0xfa, 0x3c, 0x4c, 0xf3, 0x62, 0xba,
-	0x95, 0x4c, 0x1b, 0xb1, 0xb2, 0x5b, 0xf2, 0x1c, 0xc7, 0x18, 0x7c, 0xd3, 0x90, 0x8f, 0x9a, 0xd4,
-	0x75, 0x44, 0xca, 0x29, 0x9b, 0xc6, 0x66, 0x0c, 0xc1, 0x0a, 0x96, 0xfe, 0x87, 0xcc, 0xc8, 0xa5,
-	0xb6, 0x08, 0xf1, 0xd1, 0x4d, 0x98, 0x31, 0x95, 0xa7, 0xb4, 0xa0, 0xa2, 0x89, 0xe0, 0x9b, 0x1f,
-	0x0e, 0x6a, 0x33, 0xea, 0x1b, 0x5b, 0x80, 0xd3, 0x78, 0x88, 0xc0, 0x34, 0xf5, 0xe4, 0x76, 0x16,
-	0x5e, 0xd9, 0xcd, 0xc9, 0x0b, 0x9d, 0xa0, 0x4f, 0x2c, 0x8d, 0xd7, 0xb2, 0x98, 0x35, 0xaa, 0x41,
-	0xbe, 0xfd, 0x5d, 0xdb, 0x89, 0x92, 0xa2, 0xc0, 0xef, 0xf4, 0xce, 0xd7, 0xd6, 0xb7, 0x02, 0x1c,
-	0x9e, 0x23, 0xc6, 0x97, 0xae, 0x6d, 0xe2, 0x1f, 0x50, 0x8b, 0x44, 0xfd, 0xf3, 0xab, 0x93, 0x6a,
-	0x22, 0xe9, 0x95, 0xe6, 0x9e, 0xac, 0x6d, 0x11, 0x6f, 0xac, 0xc8, 0xe1, 0xfb, 0xd7, 0x27, 0x8e,
-	0x0f, 0x6b, 0x74, 0x03, 0x72, 0xbc, 0xed, 0x48, 0x2f, 0xbe, 0x12, 0x15, 0xc2, 0x9d, 0x43, 0x8f,
-	0x1c, 0x0d, 0x6a, 0x69, 0x17, 0xf0, 0x43, 0x2c, 0xd0, 0x27, 0x1e, 0x24, 0xe3, 0x82, 0x9b, 0x3d,
-	0xad, 0x65, 0xe6, 0xce, 0xd2, 0x32, 0x7f, 0x9d, 0x1f, 0x89, 0x1a, 0x5e, 0xbc, 0xd0, 0x9b, 0x50,
-	0xb0, 0xa9, 0xcf, 0x17, 0x67, 0xd7, 0x91, 0x86, 0x56, 0x23, 0x65, 0xd7, 0x23, 0xc0, 0x91, 0xfa,
-	0x81, 0x13, 0x02, 0x64, 0x41, 0xae, 0xed, 0xbb, 0x3d, 0x39, 0x90, 0x9d, 0xad, 0xb2, 0xf2, 0x20,
-	0x4e, 0x8c, 0xbf, 0xe3, 0xbb, 0x3d, 0x2c, 0x98, 0xa3, 0x87, 0x90, 0x61, 0xae, 0xb8, 0x9c, 0x73,
-	0x11, 0x01, 0x52, 0x44, 0x66, 0xc7, 0xc5, 0x19, 0xe6, 0xf2, 0xf0, 0x0f, 0xd2, 0x41, 0x77, 0xf3,
-	0x39, 0x83, 0x2e, 0x09, 0xff, 0x38, 0xd2, 0x62, 0xd6, 0xbc, 0x2c, 0x78, 0x23, 0x05, 0x3b, 0xe9,
-	0x99, 0x63, 0x25, 0xfe, 0x01, 0x5c, 0x36, 0x43, 0x9f, 0x5c, 0x16, 0x3e, 0xf9, 0x0a, 0x9f, 0x1f,
-	0x56, 0x23, 0x67, 0x2c, 0x3f, 0xe5, 0x6f, 0x54, 0xbe, 0x1d, 0xff, 0xc5, 0xc8, 0xe0, 0x1e, 0x0e,
-	0x89, 0xb0, 0x64, 0x87, 0xde, 0x80, 0x19, 0xe2, 0x98, 0xbb, 0x5d, 0x72, 0xd7, 0xed, 0x74, 0xa8,
-	0xd3, 0xa9, 0x4c, 0x2d, 0x6a, 0x4b, 0xd3, 0x8d, 0x2b, 0x52, 0x97, 0x99, 0x0d, 0x15, 0x88, 0xd3,
-	0xb8, 0xc7, 0x75, 0xb8, 0xe9, 0x09, 0x3a, 0x5c, 0x14, 0xe7, 0x85, 0x93, 0xe2, 0x5c, 0xff, 0x79,
-	0x16, 0x50, 0xca, 0x63, 0xbc, 0xa6, 0x06, 0x7c, 0x05, 0x98, 0x71, 0xd4, 0x63, 0xd9, 0x35, 0xce,
-	0xab, 0x7f, 0xc5, 0xd6, 0xa7, 0xe1, 0x69, 0x99, 0xc8, 0x83, 0x12, 0xf3, 0xcd, 0x76, 0x9b, 0x5a,
-	0x42, 0x2b, 0x19, 0xf4, 0xaf, 0x3f, 0x45, 0x07, 0xf1, 0x07, 0x3c, 0x23, 0x76, 0xc7, 0x8e, 0x42,
-	0xad, 0x3c, 0x43, 0x29, 0xa7, 0x38, 0x25, 0x01, 0xbd, 0xab, 0x41, 0x99, 0xcf, 0x16, 0x2a, 0x8a,
-	0xdc, 0xac, 0xbf, 0xfc, 0xec, 0x62, 0xf1, 0x08, 0x87, 0x64, 0xcd, 0x1b, 0x85, 0xe0, 0x31, 0x69,
-	0xfa, 0xdf, 0x34, 0x58, 0x18, 0xf3, 0x48, 0xff, 0x22, 0x5e, 0x30, 0xbb, 0x90, 0xe7, 0x5d, 0x32,
-	0xea, 0x49, 0x9b, 0x67, 0xf2, 0x75, 0xd2, 0x9f, 0x93, 0x86, 0xce, 0xcf, 0x02, 0x1c, 0x0a, 0xd1,
-	0x97, 0x61, 0x26, 0xb5, 0x1b, 0x9d, 0xfe, 0x60, 0xa0, 0xff, 0x3e, 0x07, 0xe5, 0x88, 0x6f, 0xb0,
-	0xdd, 0xef, 0xf5, 0x4c, 0xff, 0x22, 0xc6, 0xd9, 0x9f, 0x68, 0x30, 0xa7, 0x06, 0x26, 0x8d, 0xaf,
-	0xa8, 0x71, 0xa6, 0x2b, 0x0a, 0x63, 0xe3, 0xaa, 0x94, 0x3d, 0xb7, 0x95, 0x16, 0x81, 0x47, 0x65,
-	0xa2, 0xdf, 0x6a, 0x70, 0x2d, 0x94, 0x22, 0x5f, 0xb8, 0x47, 0x28, 0x64, 0xa0, 0x9e, 0x87, 0x52,
-	0x9f, 0x91, 0x4a, 0x5d, 0x5b, 0x7d, 0x8a, 0x3c, 0xfc, 0x54, 0x6d, 0xd0, 0x2f, 0x35, 0xb8, 0x12,
-	0x22, 0x8c, 0xea, 0x99, 0x3b, 0x37, 0x3d, 0x3f, 0x2d, 0xf5, 0xbc, 0xb2, 0x7a, 0x9c, 0x20, 0x7c,
-	0xbc, 0x7c, 0xfd, 0x21, 0xbc, 0xd4, 0x32, 0x3b, 0xd4, 0x11, 0xc3, 0xdd, 0x26, 0x61, 0xf7, 0x3d,
-	0xfe, 0x43, 0x94, 0x4b, 0xcf, 0xec, 0x84, 0x11, 0x98, 0x55, 0x36, 0x35, 0xb3, 0x43, 0xb0, 0x80,
-	0xa0, 0x57, 0x21, 0xdf, 0xa5, 0x3d, 0xca, 0xe4, 0xdc, 0x18, 0x47, 0xf6, 0x5d, 0x7e, 0x88, 0x43,
-	0x98, 0x6e, 0x42, 0x49, 0x7d, 0x5d, 0x79, 0x11, 0x2f, 0x61, 0xef, 0x67, 0x60, 0x4a, 0xb6, 0x3c,
-	0x74, 0x5d, 0xd9, 0x0d, 0x43, 0x11, 0x95, 0xd3, 0xf7, 0x42, 0xb4, 0x25, 0xb7, 0xd2, 0xcc, 0x29,
-	0x29, 0xd3, 0x67, 0xb4, 0x6b, 0x84, 0xff, 0x19, 0xc0, 0x68, 0x3a, 0xec, 0xbe, 0xbf, 0xcd, 0x7c,
-	0xea, 0x74, 0xc2, 0x97, 0x0c, 0x65, 0x87, 0xfd, 0x2c, 0x4c, 0x11, 0x47, 0x2c, 0xbc, 0x62, 0x70,
-	0xc8, 0x37, 0x8a, 0xc3, 0x41, 0x6d, 0x6a, 0x23, 0x3c, 0xc2, 0x11, 0x8c, 0xef, 0x5c, 0xd4, 0xea,
-	0x79, 0x7c, 0x78, 0x13, 0xc3, 0x55, 0x3e, 0xdc, 0xb9, 0x9a, 0x6b, 0xf7, 0x5a, 0x62, 0xa0, 0x8b,
-	0xa1, 0x11, 0xe6, 0x5a, 0xf4, 0xf6, 0xa2, 0x60, 0xf2, 0x33, 0x1c, 0x43, 0x75, 0x02, 0xe5, 0xd1,
-	0x21, 0xf4, 0x05, 0xdc, 0x79, 0x63, 0xe7, 0xf1, 0x93, 0xea, 0xa5, 0x0f, 0x9e, 0x54, 0x2f, 0x7d,
-	0xf4, 0xa4, 0x7a, 0xe9, 0xdd, 0x61, 0x55, 0x7b, 0x3c, 0xac, 0x6a, 0x1f, 0x0c, 0xab, 0xda, 0x47,
-	0xc3, 0xaa, 0xf6, 0x97, 0x61, 0x55, 0xfb, 0xc5, 0x5f, 0xab, 0x97, 0xbe, 0x6e, 0x4c, 0xf6, 0xbf,
-	0x59, 0xfe, 0x13, 0x00, 0x00, 0xff, 0xff, 0xcb, 0x8c, 0x47, 0xb8, 0xfe, 0x22, 0x00, 0x00,
+	0xbd, 0xe3, 0x8f, 0x26, 0xfe, 0xd9, 0x69, 0x9d, 0x97, 0x96, 0x9a, 0xa5, 0xd8, 0xd9, 0x59, 0x40,
+	0x39, 0xc0, 0x78, 0x13, 0xda, 0x6d, 0x61, 0xb7, 0x0b, 0x71, 0x92, 0x46, 0x96, 0xda, 0xd4, 0xbc,
+	0x64, 0x55, 0x09, 0xe8, 0xb2, 0x93, 0x99, 0x67, 0x67, 0x88, 0x3d, 0x6f, 0x98, 0x79, 0x0e, 0x8d,
+	0x90, 0xd0, 0x22, 0xe0, 0xb0, 0x0b, 0x12, 0xdc, 0x10, 0x37, 0x38, 0x71, 0xe1, 0x2f, 0xe0, 0xc6,
+	0xad, 0xe2, 0xb4, 0x2b, 0x84, 0xd8, 0x93, 0x45, 0x8d, 0x00, 0x71, 0xe0, 0x1f, 0x08, 0x17, 0xf4,
+	0xde, 0xbc, 0x99, 0x79, 0x63, 0x27, 0x4d, 0x9d, 0xa4, 0x41, 0x82, 0x3d, 0xd5, 0xf3, 0x7e, 0xdf,
+	0xef, 0xf7, 0xfd, 0x52, 0x78, 0xd3, 0x74, 0x99, 0x4f, 0x4c, 0xc3, 0xa1, 0xf5, 0xf0, 0x57, 0xdd,
+	0xdb, 0xed, 0xd4, 0x4d, 0xcf, 0x09, 0xea, 0x16, 0x75, 0x99, 0x4f, 0xbb, 0x5e, 0xd7, 0x74, 0x49,
+	0x7d, 0x6f, 0x71, 0x9b, 0x30, 0x73, 0xa9, 0xde, 0x21, 0x2e, 0xf1, 0x4d, 0x46, 0x6c, 0xc3, 0xf3,
+	0x29, 0xa3, 0xc8, 0x08, 0xa9, 0xbe, 0xe5, 0x50, 0xf9, 0xcb, 0xf0, 0x76, 0x3b, 0x06, 0xa7, 0x37,
+	0x54, 0x7a, 0x43, 0xd2, 0xbf, 0x74, 0xfb, 0x68, 0x79, 0x01, 0x33, 0x59, 0x50, 0xdf, 0x5b, 0x34,
+	0xbb, 0xde, 0x8e, 0xb9, 0x38, 0x2a, 0xe9, 0xa5, 0x2f, 0x74, 0x1c, 0xb6, 0xd3, 0xdf, 0x36, 0x2c,
+	0xda, 0xab, 0x77, 0x68, 0x87, 0xd6, 0xc5, 0xf1, 0x76, 0xbf, 0x2d, 0xbe, 0xc4, 0x87, 0xf8, 0x25,
+	0xd1, 0x6f, 0xec, 0xde, 0x0e, 0x84, 0x14, 0xcf, 0xe9, 0x99, 0xd6, 0x8e, 0xe3, 0x12, 0x7f, 0x3f,
+	0x91, 0xd5, 0x23, 0xcc, 0xac, 0xef, 0x8d, 0x0b, 0xa9, 0x1f, 0x45, 0xe5, 0xf7, 0x5d, 0xe6, 0xf4,
+	0xc8, 0x18, 0xc1, 0x6b, 0xc7, 0x11, 0x04, 0xd6, 0x0e, 0xe9, 0x99, 0x63, 0x74, 0x5f, 0x3c, 0x8a,
+	0xae, 0xcf, 0x9c, 0x6e, 0xdd, 0x71, 0x59, 0xc0, 0xfc, 0x51, 0x22, 0xfd, 0x1f, 0x1a, 0x94, 0x96,
+	0x6d, 0xdb, 0x27, 0x41, 0xb0, 0xee, 0xd3, 0xbe, 0x87, 0xde, 0x81, 0x69, 0x6e, 0x89, 0x6d, 0x32,
+	0xb3, 0xa2, 0xcd, 0x6b, 0x0b, 0xc5, 0xa5, 0x57, 0x8d, 0x90, 0xb1, 0xa1, 0x32, 0x4e, 0x7c, 0xc2,
+	0xb1, 0x8d, 0xbd, 0x45, 0xe3, 0xc1, 0xf6, 0xb7, 0x89, 0xc5, 0xee, 0x13, 0x66, 0x36, 0xd0, 0x93,
+	0x41, 0xed, 0xc2, 0x70, 0x50, 0x83, 0xe4, 0x0c, 0xc7, 0x5c, 0x51, 0x1f, 0x4a, 0x1d, 0x2e, 0xea,
+	0x3e, 0xe9, 0x6d, 0x13, 0x3f, 0xa8, 0x64, 0xe6, 0xb3, 0x0b, 0xc5, 0xa5, 0xd7, 0x27, 0x74, 0xbb,
+	0xb1, 0x9e, 0xf0, 0x68, 0x5c, 0x91, 0x02, 0x4b, 0xca, 0x61, 0x80, 0x53, 0x62, 0xf4, 0x3f, 0x6a,
+	0x50, 0x56, 0x2d, 0xbd, 0xe7, 0x04, 0x0c, 0x7d, 0x73, 0xcc, 0x5a, 0xe3, 0xf9, 0xac, 0xe5, 0xd4,
+	0xc2, 0xd6, 0xb2, 0x14, 0x3d, 0x1d, 0x9d, 0x28, 0x96, 0x9a, 0x90, 0x77, 0x18, 0xe9, 0x45, 0x26,
+	0xbe, 0x31, 0xa9, 0x89, 0xaa, 0xba, 0x8d, 0x19, 0x29, 0x28, 0xdf, 0xe4, 0x2c, 0x71, 0xc8, 0x59,
+	0x7f, 0x2f, 0x0b, 0xb3, 0x2a, 0x5a, 0xcb, 0x64, 0xd6, 0xce, 0x39, 0x38, 0xf1, 0x47, 0x1a, 0xcc,
+	0x9a, 0xb6, 0x4d, 0xec, 0xf5, 0x33, 0x76, 0xe5, 0x27, 0xa5, 0x58, 0x6e, 0x55, 0x9a, 0x3b, 0x1e,
+	0x17, 0x88, 0xde, 0xd7, 0x60, 0xce, 0x27, 0x3d, 0xba, 0x37, 0xa2, 0x48, 0xf6, 0xf4, 0x8a, 0x7c,
+	0x4a, 0x2a, 0x32, 0x87, 0xc7, 0xf9, 0xe3, 0xc3, 0x84, 0xea, 0xff, 0xd4, 0xe0, 0xd2, 0xb2, 0xe7,
+	0x75, 0x1d, 0x62, 0x6f, 0xd1, 0xff, 0xf1, 0x6c, 0xfa, 0xb3, 0x06, 0x28, 0x6d, 0xeb, 0x39, 0xe4,
+	0x93, 0x95, 0xce, 0xa7, 0x37, 0x27, 0xce, 0xa7, 0x94, 0xc2, 0x47, 0x64, 0xd4, 0x4f, 0xb2, 0x30,
+	0x97, 0x46, 0xfc, 0x38, 0xa7, 0xfe, 0x7b, 0x39, 0xf5, 0xab, 0x1c, 0xcc, 0xad, 0x74, 0xfb, 0x01,
+	0x23, 0x7e, 0x4a, 0xc9, 0x17, 0xef, 0x8d, 0x1f, 0x68, 0x50, 0x26, 0xed, 0x36, 0xb1, 0x98, 0xb3,
+	0x47, 0xce, 0xd0, 0x19, 0x15, 0x29, 0xb5, 0xbc, 0x36, 0xc2, 0x1c, 0x8f, 0x89, 0x43, 0xdf, 0x87,
+	0xd9, 0xf8, 0xac, 0xd9, 0x6a, 0x74, 0xa9, 0xb5, 0x1b, 0xf9, 0xe1, 0xe6, 0xa4, 0x3a, 0x34, 0x5b,
+	0x1b, 0x84, 0x25, 0xa1, 0xb0, 0x36, 0xca, 0x17, 0x8f, 0x8b, 0x42, 0xb7, 0xa1, 0xc4, 0x28, 0x33,
+	0xbb, 0x91, 0xf9, 0xb9, 0x79, 0x6d, 0x21, 0x9b, 0xd4, 0x87, 0x2d, 0x05, 0x86, 0x53, 0x98, 0x68,
+	0x09, 0x40, 0x7c, 0xb7, 0xcc, 0x0e, 0x09, 0x2a, 0x79, 0x41, 0x17, 0xdf, 0xf7, 0x56, 0x0c, 0xc1,
+	0x0a, 0x16, 0xba, 0x09, 0x45, 0xab, 0xef, 0xfb, 0xc4, 0x65, 0xfc, 0xbb, 0x72, 0x51, 0x10, 0xcd,
+	0x49, 0xa2, 0xe2, 0x4a, 0x02, 0xc2, 0x2a, 0x9e, 0xfe, 0x77, 0x0d, 0x8a, 0x6b, 0x9d, 0xff, 0x83,
+	0x09, 0xe6, 0x43, 0x0d, 0x2e, 0x2b, 0x86, 0x9e, 0x43, 0xc1, 0x7d, 0x27, 0x5d, 0x70, 0x27, 0xb6,
+	0x50, 0xd1, 0xf6, 0x88, 0x6a, 0xfb, 0xd3, 0x2c, 0x94, 0x15, 0xac, 0xb0, 0xd4, 0xda, 0x00, 0x34,
+	0xbe, 0xf7, 0x33, 0xf5, 0xa1, 0xc2, 0xf7, 0xe3, 0x72, 0x7b, 0x48, 0xb9, 0xed, 0xc2, 0xb5, 0xb5,
+	0xc7, 0x8c, 0xf8, 0xae, 0xd9, 0x5d, 0x73, 0x99, 0xc3, 0xf6, 0x31, 0x69, 0x13, 0x9f, 0xb8, 0x16,
+	0x41, 0xf3, 0x90, 0x73, 0xcd, 0x1e, 0x11, 0xee, 0x28, 0x34, 0x4a, 0x92, 0x75, 0x6e, 0xc3, 0xec,
+	0x11, 0x2c, 0x20, 0xa8, 0x0e, 0x05, 0xfe, 0x6f, 0xe0, 0x99, 0x16, 0xa9, 0x64, 0x04, 0xda, 0xac,
+	0x44, 0x2b, 0x6c, 0x44, 0x00, 0x9c, 0xe0, 0xe8, 0xff, 0xd6, 0xa0, 0x2c, 0xc4, 0x2f, 0x07, 0x01,
+	0xb5, 0x1c, 0x93, 0x39, 0xd4, 0x3d, 0x9f, 0x3e, 0x5b, 0x36, 0xa5, 0x44, 0x69, 0xff, 0x89, 0x47,
+	0x0a, 0x41, 0x1d, 0x5f, 0x52, 0x52, 0xdc, 0x97, 0x47, 0xf8, 0xe3, 0x31, 0x89, 0xfa, 0x87, 0x59,
+	0x28, 0x2a, 0x97, 0x8f, 0x1e, 0x42, 0xd6, 0xa3, 0xb6, 0xb4, 0x79, 0xe2, 0x5d, 0xa1, 0x45, 0xed,
+	0x44, 0x8d, 0xa9, 0xe1, 0xa0, 0x96, 0xe5, 0x27, 0x9c, 0x23, 0xfa, 0xa1, 0x06, 0x97, 0x48, 0xca,
+	0xab, 0xc2, 0x3b, 0xc5, 0xa5, 0xf5, 0x89, 0xf3, 0xf9, 0xf0, 0xd8, 0x68, 0xa0, 0xe1, 0xa0, 0x76,
+	0x69, 0x04, 0x38, 0x22, 0x12, 0x7d, 0x0e, 0xb2, 0x8e, 0x17, 0x86, 0x75, 0xa9, 0x71, 0x85, 0x2b,
+	0xd8, 0x6c, 0x05, 0x07, 0x83, 0x5a, 0xa1, 0xd9, 0x92, 0x0b, 0x0c, 0xe6, 0x08, 0xe8, 0x6d, 0xc8,
+	0x7b, 0xd4, 0x67, 0xbc, 0xd9, 0x70, 0x8f, 0x7c, 0x69, 0x52, 0x1d, 0x79, 0xa4, 0xd9, 0x2d, 0xea,
+	0xb3, 0xa4, 0xe2, 0xf0, 0xaf, 0x00, 0x87, 0x6c, 0xd1, 0x37, 0x20, 0xe7, 0x52, 0x9b, 0x88, 0x9e,
+	0x54, 0x5c, 0xba, 0x33, 0x31, 0x7b, 0x6a, 0x93, 0xc4, 0xf0, 0x69, 0x91, 0x02, 0xfc, 0x48, 0x30,
+	0xd5, 0x7f, 0xa3, 0xc1, 0xa5, 0x74, 0x48, 0xa4, 0xb3, 0x42, 0x3b, 0x3e, 0x2b, 0xe2, 0x44, 0xcb,
+	0x1c, 0x99, 0x68, 0x0d, 0xc8, 0xf6, 0x1d, 0xbb, 0x92, 0x15, 0x08, 0xaf, 0x4a, 0x84, 0xec, 0x5b,
+	0xcd, 0xd5, 0x83, 0x41, 0xed, 0xe5, 0xa3, 0x5e, 0x01, 0xd8, 0xbe, 0x47, 0x02, 0xe3, 0xad, 0xe6,
+	0x2a, 0xe6, 0xc4, 0xfa, 0xef, 0x35, 0x98, 0x92, 0x7d, 0x1e, 0x3d, 0x84, 0x9c, 0xe5, 0xd8, 0xbe,
+	0x0c, 0xbd, 0x13, 0x4e, 0x16, 0xb1, 0xa2, 0x2b, 0xcd, 0x55, 0x8c, 0x05, 0x43, 0xf4, 0x08, 0x2e,
+	0x92, 0xc7, 0x16, 0xf1, 0x98, 0x4c, 0xaf, 0x13, 0xb2, 0xbe, 0x24, 0x59, 0x5f, 0x5c, 0x13, 0xcc,
+	0xb0, 0x64, 0xaa, 0xb7, 0x21, 0x2f, 0x10, 0xd0, 0x2b, 0x90, 0x71, 0x3c, 0xa1, 0x7e, 0xa9, 0x31,
+	0x37, 0x1c, 0xd4, 0x32, 0xcd, 0x56, 0x3a, 0xb2, 0x32, 0x8e, 0xc7, 0x87, 0x19, 0xcf, 0x27, 0x6d,
+	0xe7, 0xf1, 0x3d, 0xe2, 0x76, 0xd8, 0x8e, 0xb8, 0xdf, 0x7c, 0xd2, 0x78, 0x5b, 0x0a, 0x0c, 0xa7,
+	0x30, 0xf5, 0x5f, 0x6a, 0x80, 0xee, 0xf7, 0xbb, 0xcc, 0xb1, 0xcc, 0x80, 0x09, 0xf7, 0x36, 0xdd,
+	0x36, 0x45, 0xaf, 0x40, 0x5e, 0xf4, 0x67, 0xe9, 0xd5, 0x38, 0xdc, 0xc2, 0x00, 0x08, 0x61, 0xe8,
+	0x6d, 0xc8, 0x79, 0xd4, 0x3e, 0xf1, 0x13, 0x40, 0x2a, 0xad, 0xe3, 0x2b, 0x6e, 0x51, 0x3b, 0xc0,
+	0x82, 0xaf, 0xfe, 0x9e, 0x06, 0x85, 0x38, 0xe4, 0x79, 0xec, 0xf0, 0x28, 0x17, 0x1a, 0xe5, 0x55,
+	0x7c, 0x9f, 0x61, 0x01, 0x79, 0x8e, 0xe8, 0xba, 0x0d, 0xd3, 0xe2, 0x6d, 0xc8, 0xa2, 0x5d, 0x19,
+	0x62, 0xd7, 0xa3, 0x11, 0xa1, 0x25, 0xcf, 0x0f, 0x94, 0xdf, 0x38, 0xc6, 0xd6, 0xff, 0x95, 0x85,
+	0x99, 0x0d, 0xc2, 0xbe, 0x4b, 0xfd, 0xdd, 0x16, 0xed, 0x3a, 0xd6, 0xfe, 0x39, 0x14, 0xf3, 0x36,
+	0xe4, 0xfd, 0x7e, 0x97, 0x44, 0x17, 0xbc, 0x3c, 0x71, 0x3e, 0xab, 0xfa, 0xe2, 0x7e, 0x97, 0x24,
+	0x7e, 0xe4, 0x5f, 0x01, 0x0e, 0xd9, 0xa3, 0x3b, 0x70, 0xd9, 0x4c, 0x6d, 0x85, 0x61, 0x29, 0x2b,
+	0x88, 0x78, 0xbb, 0x9c, 0x5e, 0x18, 0x03, 0x3c, 0x8a, 0x8b, 0x16, 0xf8, 0xa5, 0x3a, 0xd4, 0xe7,
+	0xc5, 0x97, 0x4f, 0xd1, 0x5a, 0xa3, 0x14, 0x5e, 0x68, 0x78, 0x86, 0x63, 0x28, 0xba, 0x01, 0x25,
+	0xe6, 0x10, 0x3f, 0x82, 0x88, 0x3a, 0x95, 0x6f, 0x94, 0xc5, 0xbc, 0xad, 0x9c, 0xe3, 0x14, 0x16,
+	0x0a, 0xa0, 0x10, 0xd0, 0xbe, 0x6f, 0xf1, 0xda, 0x24, 0x26, 0xe7, 0xe2, 0xd2, 0xdd, 0xd3, 0x5d,
+	0x45, 0x1c, 0x75, 0x33, 0xbc, 0x52, 0x6d, 0x46, 0xcc, 0x71, 0x22, 0x47, 0xff, 0x93, 0x06, 0xb3,
+	0x29, 0xa2, 0x73, 0x18, 0x49, 0xb7, 0xd3, 0x23, 0xe9, 0x9d, 0x53, 0x19, 0x79, 0xc4, 0x50, 0xfa,
+	0x3d, 0xb8, 0x96, 0x42, 0xe3, 0x05, 0x7e, 0x93, 0x99, 0xac, 0x1f, 0xa0, 0xcf, 0xc3, 0x34, 0x2f,
+	0xf4, 0x1b, 0xc9, 0x24, 0x14, 0x2b, 0xbb, 0x21, 0xcf, 0x71, 0x8c, 0xc1, 0xb7, 0x20, 0xf9, 0xe0,
+	0xea, 0x50, 0x57, 0xa4, 0x9c, 0xb2, 0x05, 0xad, 0xc7, 0x10, 0xac, 0x60, 0xe9, 0x7f, 0xc8, 0x8c,
+	0x5c, 0x6a, 0x8b, 0x10, 0x1f, 0xdd, 0x82, 0x19, 0x53, 0x79, 0xe6, 0x0b, 0x2a, 0x9a, 0x08, 0xbe,
+	0xd9, 0xe1, 0xa0, 0x36, 0xa3, 0xbe, 0xff, 0x05, 0x38, 0x8d, 0x87, 0x08, 0x4c, 0x3b, 0x9e, 0xdc,
+	0x1c, 0xc3, 0x2b, 0xbb, 0x35, 0x79, 0x11, 0x16, 0xf4, 0x89, 0xa5, 0xf1, 0xca, 0x18, 0xb3, 0x46,
+	0x35, 0xc8, 0xb7, 0xbf, 0x63, 0xbb, 0x51, 0x52, 0x14, 0xf8, 0x9d, 0xde, 0xfd, 0xda, 0xea, 0x46,
+	0x80, 0xc3, 0x73, 0xc4, 0xf8, 0x42, 0xb8, 0x49, 0xfc, 0x3d, 0xc7, 0x22, 0x51, 0x6f, 0xff, 0xea,
+	0xa4, 0x9a, 0x48, 0x7a, 0x65, 0xf0, 0x48, 0x56, 0xca, 0x88, 0x37, 0x56, 0xe4, 0xf0, 0xdd, 0xf0,
+	0x13, 0x87, 0x87, 0x35, 0xba, 0x09, 0x39, 0xde, 0x12, 0xa5, 0x17, 0x5f, 0x8e, 0x0a, 0xe1, 0xd6,
+	0xbe, 0x47, 0x0e, 0x06, 0xb5, 0xb4, 0x0b, 0xf8, 0x21, 0x16, 0xe8, 0x13, 0x0f, 0xb9, 0x71, 0xc1,
+	0xcd, 0x1e, 0xd7, 0xce, 0x73, 0xa7, 0x69, 0xe7, 0xbf, 0xce, 0x8f, 0x44, 0x0d, 0x2f, 0x5e, 0xe8,
+	0x0d, 0x28, 0xd8, 0x8e, 0xcf, 0x97, 0x7a, 0xea, 0x4a, 0x43, 0xab, 0x91, 0xb2, 0xab, 0x11, 0xe0,
+	0x40, 0xfd, 0xc0, 0x09, 0x01, 0xb2, 0x20, 0xd7, 0xf6, 0x69, 0x4f, 0x0e, 0x8b, 0xa7, 0xab, 0xac,
+	0x3c, 0x88, 0x13, 0xe3, 0xef, 0xfa, 0xb4, 0x87, 0x05, 0x73, 0xf4, 0x08, 0x32, 0x8c, 0x8a, 0xcb,
+	0x39, 0x13, 0x11, 0x20, 0x45, 0x64, 0xb6, 0x28, 0xce, 0x30, 0xca, 0xc3, 0x3f, 0x48, 0x07, 0xdd,
+	0xad, 0x13, 0x06, 0x5d, 0x12, 0xfe, 0x71, 0xa4, 0xc5, 0xac, 0x79, 0x59, 0xf0, 0x46, 0x0a, 0x76,
+	0xd2, 0x33, 0xc7, 0x4a, 0xfc, 0x43, 0xb8, 0x68, 0x86, 0x3e, 0xb9, 0x28, 0x7c, 0xf2, 0x15, 0x3e,
+	0xdb, 0x2c, 0x47, 0xce, 0x58, 0x7c, 0xc6, 0xdf, 0xcf, 0x7c, 0x3b, 0xfe, 0x6b, 0x96, 0xc1, 0x3d,
+	0x1c, 0x12, 0x61, 0xc9, 0x0e, 0xbd, 0x0e, 0x33, 0xc4, 0x35, 0xb7, 0xbb, 0xe4, 0x1e, 0xed, 0x74,
+	0x1c, 0xb7, 0x53, 0x99, 0x9a, 0xd7, 0x16, 0xa6, 0x1b, 0x57, 0xa5, 0x2e, 0x33, 0x6b, 0x2a, 0x10,
+	0xa7, 0x71, 0x0f, 0xeb, 0x70, 0xd3, 0x13, 0x74, 0xb8, 0x28, 0xce, 0x0b, 0x47, 0xc5, 0xb9, 0xfe,
+	0xb3, 0x2c, 0xa0, 0x94, 0xc7, 0x78, 0x4d, 0x0d, 0xf8, 0x7a, 0x32, 0xe3, 0xaa, 0xc7, 0xb2, 0x6b,
+	0x9c, 0x55, 0xff, 0x8a, 0xad, 0x4f, 0xc3, 0xd3, 0x32, 0x91, 0x07, 0x25, 0xe6, 0x9b, 0xed, 0xb6,
+	0x63, 0x09, 0xad, 0x64, 0xd0, 0xbf, 0xf6, 0x0c, 0x1d, 0xc4, 0x1f, 0x17, 0x8d, 0xd8, 0x1d, 0x5b,
+	0x0a, 0xb5, 0xf2, 0x44, 0xa6, 0x9c, 0xe2, 0x94, 0x04, 0xf4, 0xae, 0x06, 0x65, 0x3e, 0x5b, 0xa8,
+	0x28, 0x72, 0xeb, 0xff, 0xf2, 0xf3, 0x8b, 0xc5, 0x23, 0x1c, 0x92, 0x15, 0x74, 0x14, 0x82, 0xc7,
+	0xa4, 0xe9, 0x7f, 0xd3, 0x60, 0x6e, 0xcc, 0x23, 0xfd, 0xf3, 0x78, 0x5d, 0xed, 0x42, 0x9e, 0x77,
+	0xc9, 0xa8, 0x27, 0xad, 0x9f, 0xca, 0xd7, 0x49, 0x7f, 0x4e, 0x1a, 0x3a, 0x3f, 0x0b, 0x70, 0x28,
+	0x44, 0x5f, 0x84, 0x99, 0xd4, 0xde, 0x76, 0xfc, 0x63, 0x86, 0xfe, 0xbb, 0x3c, 0x94, 0x23, 0xbe,
+	0xc1, 0x66, 0xbf, 0xd7, 0x33, 0xfd, 0xf3, 0x18, 0x67, 0x7f, 0xac, 0xc1, 0x65, 0x35, 0x30, 0x9d,
+	0xf8, 0x8a, 0x1a, 0xa7, 0xba, 0xa2, 0x30, 0x36, 0xae, 0x49, 0xd9, 0x97, 0x37, 0xd2, 0x22, 0xf0,
+	0xa8, 0x4c, 0xf4, 0x5b, 0x0d, 0xae, 0x87, 0x52, 0xe4, 0xeb, 0xfb, 0x08, 0x85, 0x0c, 0xd4, 0xb3,
+	0x50, 0xea, 0x33, 0x52, 0xa9, 0xeb, 0xcb, 0xcf, 0x90, 0x87, 0x9f, 0xa9, 0x0d, 0xfa, 0x85, 0x06,
+	0x57, 0x43, 0x84, 0x51, 0x3d, 0x73, 0x67, 0xa6, 0xe7, 0xa7, 0xa5, 0x9e, 0x57, 0x97, 0x0f, 0x13,
+	0x84, 0x0f, 0x97, 0xcf, 0x07, 0xf3, 0x5e, 0xb4, 0x3a, 0x56, 0xf2, 0x27, 0x53, 0x66, 0x7c, 0xf7,
+	0x4c, 0x66, 0x8e, 0x18, 0x86, 0x13, 0x39, 0xfa, 0x23, 0xb8, 0xd2, 0x32, 0x3b, 0x8e, 0x2b, 0x26,
+	0xca, 0x75, 0xc2, 0x1e, 0x78, 0xfc, 0x87, 0xa8, 0xd1, 0x9e, 0xd9, 0x09, 0xc3, 0x3e, 0xab, 0xac,
+	0x87, 0x66, 0x87, 0x60, 0x01, 0xe1, 0x3b, 0x6d, 0xd7, 0xe9, 0x39, 0x4c, 0x0e, 0xab, 0x71, 0x3a,
+	0xdd, 0xe3, 0x87, 0x38, 0x84, 0xe9, 0x26, 0x94, 0xd4, 0xbd, 0xf4, 0x45, 0x3c, 0x0d, 0xbe, 0x9f,
+	0x81, 0x29, 0xd9, 0x67, 0xd1, 0x0d, 0x65, 0x21, 0x0d, 0x45, 0x54, 0x8e, 0x5f, 0x46, 0xd1, 0x86,
+	0x5c, 0x85, 0x33, 0xc7, 0xe4, 0x69, 0x9f, 0x39, 0x5d, 0x23, 0xfc, 0xdf, 0x11, 0x46, 0xd3, 0x65,
+	0x0f, 0xfc, 0x4d, 0xe6, 0x3b, 0x6e, 0x27, 0x7c, 0xda, 0x51, 0x16, 0xe7, 0xcf, 0xc2, 0x14, 0x71,
+	0xc5, 0x96, 0x2d, 0xa6, 0x95, 0x7c, 0xa3, 0x38, 0x1c, 0xd4, 0xa6, 0xd6, 0xc2, 0x23, 0x1c, 0xc1,
+	0xf8, 0xa2, 0xe7, 0x58, 0x3d, 0x8f, 0x4f, 0x8c, 0x62, 0xa2, 0xcb, 0x87, 0x8b, 0x5e, 0x73, 0xe5,
+	0x7e, 0x4b, 0x4c, 0x91, 0x31, 0x34, 0xc2, 0x5c, 0x89, 0x1e, 0xa3, 0x14, 0x4c, 0x7e, 0x86, 0x63,
+	0xa8, 0x4e, 0xa0, 0x3c, 0x3a, 0xf9, 0xbe, 0x80, 0x3b, 0x6f, 0x6c, 0x3d, 0x79, 0x5a, 0xbd, 0xf0,
+	0xc1, 0xd3, 0xea, 0x85, 0x8f, 0x9e, 0x56, 0x2f, 0xbc, 0x3b, 0xac, 0x6a, 0x4f, 0x86, 0x55, 0xed,
+	0x83, 0x61, 0x55, 0xfb, 0x68, 0x58, 0xd5, 0xfe, 0x32, 0xac, 0x6a, 0x3f, 0xff, 0x6b, 0xf5, 0xc2,
+	0xd7, 0x8d, 0xc9, 0xfe, 0x7b, 0xcf, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xa6, 0x1d, 0x87, 0x1b,
+	0x0f, 0x24, 0x00, 0x00,
 }
 
 func (m *AddressGroup) Marshal() (dAtA []byte, err error) {
@@ -1901,6 +1935,48 @@ func (m *IPNet) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 	return len(dAtA) - i, nil
 }
 
+func (m *MulticastGroupInfo) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *MulticastGroupInfo) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MulticastGroupInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if len(m.Pods) > 0 {
+		for iNdEx := len(m.Pods) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.Pods[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintGenerated(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x12
+		}
+	}
+	i -= len(m.Group)
+	copy(dAtA[i:], m.Group)
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.Group)))
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
 func (m *NamedPort) Marshal() (dAtA []byte, err error) {
 	size := m.Size()
 	dAtA = make([]byte, size)
@@ -2452,6 +2528,20 @@ func (m *NodeStatsSummary) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 	_ = i
 	var l int
 	_ = l
+	if len(m.Multicast) > 0 {
+		for iNdEx := len(m.Multicast) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.Multicast[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintGenerated(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x2a
+		}
+	}
 	if len(m.AntreaNetworkPolicies) > 0 {
 		for iNdEx := len(m.AntreaNetworkPolicies) - 1; iNdEx >= 0; iNdEx-- {
 			{
@@ -2976,6 +3066,23 @@ func (m *IPNet) Size() (n int) {
 	return n
 }
 
+func (m *MulticastGroupInfo) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Group)
+	n += 1 + l + sovGenerated(uint64(l))
+	if len(m.Pods) > 0 {
+		for _, e := range m.Pods {
+			l = e.Size()
+			n += 1 + l + sovGenerated(uint64(l))
+		}
+	}
+	return n
+}
+
 func (m *NamedPort) Size() (n int) {
 	if m == nil {
 		return 0
@@ -3210,6 +3317,12 @@ func (m *NodeStatsSummary) Size() (n int) {
 			n += 1 + l + sovGenerated(uint64(l))
 		}
 	}
+	if len(m.Multicast) > 0 {
+		for _, e := range m.Multicast {
+			l = e.Size()
+			n += 1 + l + sovGenerated(uint64(l))
+		}
+	}
 	return n
 }
 
@@ -3554,6 +3667,22 @@ func (this *IPNet) String() string {
 	}, "")
 	return s
 }
+func (this *MulticastGroupInfo) String() string {
+	if this == nil {
+		return "nil"
+	}
+	repeatedStringForPods := "[]PodReference{"
+	for _, f := range this.Pods {
+		repeatedStringForPods += strings.Replace(strings.Replace(f.String(), "PodReference", "PodReference", 1), `&`, ``, 1) + ","
+	}
+	repeatedStringForPods += "}"
+	s := strings.Join([]string{`&MulticastGroupInfo{`,
+		`Group:` + fmt.Sprintf("%v", this.Group) + `,`,
+		`Pods:` + repeatedStringForPods + `,`,
+		`}`,
+	}, "")
+	return s
+}
 func (this *NamedPort) String() string {
 	if this == nil {
 		return "nil"
@@ -3734,11 +3863,17 @@ func (this *NodeStatsSummary) String() string {
 		repeatedStringForAntreaNetworkPolicies += strings.Replace(strings.Replace(f.String(), "NetworkPolicyStats", "NetworkPolicyStats", 1), `&`, ``, 1) + ","
 	}
 	repeatedStringForAntreaNetworkPolicies += "}"
+	repeatedStringForMulticast := "[]MulticastGroupInfo{"
+	for _, f := range this.Multicast {
+		repeatedStringForMulticast += strings.Replace(strings.Replace(f.String(), "MulticastGroupInfo", "MulticastGroupInfo", 1), `&`, ``, 1) + ","
+	}
+	repeatedStringForMulticast += "}"
 	s := strings.Join([]string{`&NodeStatsSummary{`,
 		`ObjectMeta:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.ObjectMeta), "ObjectMeta", "v1.ObjectMeta", 1), `&`, ``, 1) + `,`,
 		`NetworkPolicies:` + repeatedStringForNetworkPolicies + `,`,
 		`AntreaClusterNetworkPolicies:` + repeatedStringForAntreaClusterNetworkPolicies + `,`,
 		`AntreaNetworkPolicies:` + repeatedStringForAntreaNetworkPolicies + `,`,
+		`Multicast:` + repeatedStringForMulticast + `,`,
 		`}`,
 	}, "")
 	return s
@@ -5982,6 +6117,122 @@ func (m *IPNet) Unmarshal(dAtA []byte) error {
 	}
 	return nil
 }
+func (m *MulticastGroupInfo) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGenerated
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: MulticastGroupInfo: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: MulticastGroupInfo: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Group", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Group = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Pods", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Pods = append(m.Pods, PodReference{})
+			if err := m.Pods[len(m.Pods)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGenerated(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if (skippy < 0) || (iNdEx+skippy) < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
 func (m *NamedPort) Unmarshal(dAtA []byte) error {
 	l := len(dAtA)
 	iNdEx := 0
@@ -7741,6 +7992,40 @@ func (m *NodeStatsSummary) Unmarshal(dAtA []byte) error {
 				return err
 			}
 			iNdEx = postIndex
+		case 5:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Multicast", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Multicast = append(m.Multicast, MulticastGroupInfo{})
+			if err := m.Multicast[len(m.Multicast)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
 			skippy, err := skipGenerated(dAtA[iNdEx:])
diff --git a/pkg/apis/controlplane/v1beta2/generated.proto b/pkg/apis/controlplane/v1beta2/generated.proto
index 718ced276..e1a23bf4a 100644
--- a/pkg/apis/controlplane/v1beta2/generated.proto
+++ b/pkg/apis/controlplane/v1beta2/generated.proto
@@ -178,6 +178,15 @@ message IPNet {
   optional int32 prefixLength = 2;
 }
 
+// MulticastGroupInfo contains the list of Pods that have joined a multicast group, for a given Node.
+message MulticastGroupInfo {
+  // Group is the IP of the multicast group.
+  optional string group = 1;
+
+  // Pods is the list of Pods that have joined the multicast group.
+  repeated PodReference pods = 2;
+}
+
 // NamedPort represents a Port with a name on Pod.
 message NamedPort {
   // Port represents the Port number.
@@ -337,6 +346,9 @@ message NodeStatsSummary {
 
   // The TrafficStats of Antrea NetworkPolicies collected from the Node.
   repeated NetworkPolicyStats antreaNetworkPolicies = 4;
+
+  // Multicast group information collected from the Node.
+  repeated MulticastGroupInfo multicast = 5;
 }
 
 message PaginationGetOptions {
diff --git a/pkg/apis/controlplane/v1beta2/types.go b/pkg/apis/controlplane/v1beta2/types.go
index e56f4ab03..5ac4d8b4a 100644
--- a/pkg/apis/controlplane/v1beta2/types.go
+++ b/pkg/apis/controlplane/v1beta2/types.go
@@ -342,6 +342,16 @@ type NodeStatsSummary struct {
 	AntreaClusterNetworkPolicies []NetworkPolicyStats `json:"antreaClusterNetworkPolicies,omitempty" protobuf:"bytes,3,rep,name=antreaClusterNetworkPolicies"`
 	// The TrafficStats of Antrea NetworkPolicies collected from the Node.
 	AntreaNetworkPolicies []NetworkPolicyStats `json:"antreaNetworkPolicies,omitempty" protobuf:"bytes,4,rep,name=antreaNetworkPolicies"`
+	// Multicast group information collected from the Node.
+	Multicast []MulticastGroupInfo `json:"multicast,omitempty" protobuf:"bytes,5,rep,name=multicast"`
+}
+
+// MulticastGroupInfo contains the list of Pods that have joined a multicast group, for a given Node.
+type MulticastGroupInfo struct {
+	// Group is the IP of the multicast group.
+	Group string `json:"group,omitempty" protobuf:"bytes,1,opt,name=group"`
+	// Pods is the list of Pods that have joined the multicast group.
+	Pods []PodReference `json:"pods,omitempty" protobuf:"bytes,2,rep,name=pods"`
 }
 
 // NetworkPolicyStats contains the information and traffic stats of a NetworkPolicy.
diff --git a/pkg/apis/controlplane/v1beta2/zz_generated.conversion.go b/pkg/apis/controlplane/v1beta2/zz_generated.conversion.go
index b0c7b6d6f..91049c1b2 100644
--- a/pkg/apis/controlplane/v1beta2/zz_generated.conversion.go
+++ b/pkg/apis/controlplane/v1beta2/zz_generated.conversion.go
@@ -199,6 +199,16 @@ func RegisterConversions(s *runtime.Scheme) error {
 	}); err != nil {
 		return err
 	}
+	if err := s.AddGeneratedConversionFunc((*MulticastGroupInfo)(nil), (*controlplane.MulticastGroupInfo)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1beta2_MulticastGroupInfo_To_controlplane_MulticastGroupInfo(a.(*MulticastGroupInfo), b.(*controlplane.MulticastGroupInfo), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*controlplane.MulticastGroupInfo)(nil), (*MulticastGroupInfo)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_controlplane_MulticastGroupInfo_To_v1beta2_MulticastGroupInfo(a.(*controlplane.MulticastGroupInfo), b.(*MulticastGroupInfo), scope)
+	}); err != nil {
+		return err
+	}
 	if err := s.AddGeneratedConversionFunc((*NamedPort)(nil), (*controlplane.NamedPort)(nil), func(a, b interface{}, scope conversion.Scope) error {
 		return Convert_v1beta2_NamedPort_To_controlplane_NamedPort(a.(*NamedPort), b.(*controlplane.NamedPort), scope)
 	}); err != nil {
@@ -995,6 +1005,28 @@ func Convert_controlplane_IPNet_To_v1beta2_IPNet(in *controlplane.IPNet, out *IP
 	return autoConvert_controlplane_IPNet_To_v1beta2_IPNet(in, out, s)
 }
 
+func autoConvert_v1beta2_MulticastGroupInfo_To_controlplane_MulticastGroupInfo(in *MulticastGroupInfo, out *controlplane.MulticastGroupInfo, s conversion.Scope) error {
+	out.Group = in.Group
+	out.Pods = *(*[]controlplane.PodReference)(unsafe.Pointer(&in.Pods))
+	return nil
+}
+
+// Convert_v1beta2_MulticastGroupInfo_To_controlplane_MulticastGroupInfo is an autogenerated conversion function.
+func Convert_v1beta2_MulticastGroupInfo_To_controlplane_MulticastGroupInfo(in *MulticastGroupInfo, out *controlplane.MulticastGroupInfo, s conversion.Scope) error {
+	return autoConvert_v1beta2_MulticastGroupInfo_To_controlplane_MulticastGroupInfo(in, out, s)
+}
+
+func autoConvert_controlplane_MulticastGroupInfo_To_v1beta2_MulticastGroupInfo(in *controlplane.MulticastGroupInfo, out *MulticastGroupInfo, s conversion.Scope) error {
+	out.Group = in.Group
+	out.Pods = *(*[]PodReference)(unsafe.Pointer(&in.Pods))
+	return nil
+}
+
+// Convert_controlplane_MulticastGroupInfo_To_v1beta2_MulticastGroupInfo is an autogenerated conversion function.
+func Convert_controlplane_MulticastGroupInfo_To_v1beta2_MulticastGroupInfo(in *controlplane.MulticastGroupInfo, out *MulticastGroupInfo, s conversion.Scope) error {
+	return autoConvert_controlplane_MulticastGroupInfo_To_v1beta2_MulticastGroupInfo(in, out, s)
+}
+
 func autoConvert_v1beta2_NamedPort_To_controlplane_NamedPort(in *NamedPort, out *controlplane.NamedPort, s conversion.Scope) error {
 	out.Port = in.Port
 	out.Name = in.Name
@@ -1304,6 +1336,7 @@ func autoConvert_v1beta2_NodeStatsSummary_To_controlplane_NodeStatsSummary(in *N
 	out.NetworkPolicies = *(*[]controlplane.NetworkPolicyStats)(unsafe.Pointer(&in.NetworkPolicies))
 	out.AntreaClusterNetworkPolicies = *(*[]controlplane.NetworkPolicyStats)(unsafe.Pointer(&in.AntreaClusterNetworkPolicies))
 	out.AntreaNetworkPolicies = *(*[]controlplane.NetworkPolicyStats)(unsafe.Pointer(&in.AntreaNetworkPolicies))
+	out.Multicast = *(*[]controlplane.MulticastGroupInfo)(unsafe.Pointer(&in.Multicast))
 	return nil
 }
 
@@ -1317,6 +1350,7 @@ func autoConvert_controlplane_NodeStatsSummary_To_v1beta2_NodeStatsSummary(in *c
 	out.NetworkPolicies = *(*[]NetworkPolicyStats)(unsafe.Pointer(&in.NetworkPolicies))
 	out.AntreaClusterNetworkPolicies = *(*[]NetworkPolicyStats)(unsafe.Pointer(&in.AntreaClusterNetworkPolicies))
 	out.AntreaNetworkPolicies = *(*[]NetworkPolicyStats)(unsafe.Pointer(&in.AntreaNetworkPolicies))
+	out.Multicast = *(*[]MulticastGroupInfo)(unsafe.Pointer(&in.Multicast))
 	return nil
 }
 
diff --git a/pkg/apis/controlplane/v1beta2/zz_generated.deepcopy.go b/pkg/apis/controlplane/v1beta2/zz_generated.deepcopy.go
index 5e05b5486..957f7416c 100644
--- a/pkg/apis/controlplane/v1beta2/zz_generated.deepcopy.go
+++ b/pkg/apis/controlplane/v1beta2/zz_generated.deepcopy.go
@@ -559,6 +559,27 @@ func (in *IPNet) DeepCopy() *IPNet {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *MulticastGroupInfo) DeepCopyInto(out *MulticastGroupInfo) {
+	*out = *in
+	if in.Pods != nil {
+		in, out := &in.Pods, &out.Pods
+		*out = make([]PodReference, len(*in))
+		copy(*out, *in)
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MulticastGroupInfo.
+func (in *MulticastGroupInfo) DeepCopy() *MulticastGroupInfo {
+	if in == nil {
+		return nil
+	}
+	out := new(MulticastGroupInfo)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *NamedPort) DeepCopyInto(out *NamedPort) {
 	*out = *in
@@ -862,6 +883,13 @@ func (in *NodeStatsSummary) DeepCopyInto(out *NodeStatsSummary) {
 			(*in)[i].DeepCopyInto(&(*out)[i])
 		}
 	}
+	if in.Multicast != nil {
+		in, out := &in.Multicast, &out.Multicast
+		*out = make([]MulticastGroupInfo, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
 	return
 }
 
diff --git a/pkg/apis/controlplane/zz_generated.deepcopy.go b/pkg/apis/controlplane/zz_generated.deepcopy.go
index 15a25fbbb..e5ca10a32 100644
--- a/pkg/apis/controlplane/zz_generated.deepcopy.go
+++ b/pkg/apis/controlplane/zz_generated.deepcopy.go
@@ -559,6 +559,27 @@ func (in *IPNet) DeepCopy() *IPNet {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *MulticastGroupInfo) DeepCopyInto(out *MulticastGroupInfo) {
+	*out = *in
+	if in.Pods != nil {
+		in, out := &in.Pods, &out.Pods
+		*out = make([]PodReference, len(*in))
+		copy(*out, *in)
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MulticastGroupInfo.
+func (in *MulticastGroupInfo) DeepCopy() *MulticastGroupInfo {
+	if in == nil {
+		return nil
+	}
+	out := new(MulticastGroupInfo)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *NamedPort) DeepCopyInto(out *NamedPort) {
 	*out = *in
@@ -862,6 +883,13 @@ func (in *NodeStatsSummary) DeepCopyInto(out *NodeStatsSummary) {
 			(*in)[i].DeepCopyInto(&(*out)[i])
 		}
 	}
+	if in.Multicast != nil {
+		in, out := &in.Multicast, &out.Multicast
+		*out = make([]MulticastGroupInfo, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
 	return
 }
 
diff --git a/pkg/apis/stats/register.go b/pkg/apis/stats/register.go
index 5f60829f1..6ecb66e61 100644
--- a/pkg/apis/stats/register.go
+++ b/pkg/apis/stats/register.go
@@ -50,6 +50,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
 		&AntreaNetworkPolicyStatsList{},
 		&NetworkPolicyStats{},
 		&NetworkPolicyStatsList{},
+		&MulticastGroup{},
+		&MulticastGroupList{},
 	)
 	return nil
 }
diff --git a/pkg/apis/stats/types.go b/pkg/apis/stats/types.go
index f99886e1a..e293b3352 100644
--- a/pkg/apis/stats/types.go
+++ b/pkg/apis/stats/types.go
@@ -65,6 +65,38 @@ type AntreaNetworkPolicyStatsList struct {
 	Items []AntreaNetworkPolicyStats
 }
 
+// PodReference represents a Pod Reference.
+type PodReference struct {
+	// The name of this Pod.
+	Name string
+	// The namespace of this Pod.
+	Namespace string
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// MulticastGroup contains the mapping between multicast group and Pods.
+type MulticastGroup struct {
+	metav1.TypeMeta
+	metav1.ObjectMeta
+
+	// Group is the IP of the multicast group.
+	Group string
+	// Pods is the list of Pods that have joined the multicast group.
+	Pods []PodReference
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// MulticastGroupList is a list of MulticastGroup.
+type MulticastGroupList struct {
+	metav1.TypeMeta
+	metav1.ListMeta
+
+	// List of MulticastGroup.
+	Items []MulticastGroup
+}
+
 // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 
 // NetworkPolicyStats is the statistics of a K8s NetworkPolicy.
diff --git a/pkg/apis/stats/v1alpha1/generated.pb.go b/pkg/apis/stats/v1alpha1/generated.pb.go
index dafc3c63d..97c8feb6c 100644
--- a/pkg/apis/stats/v1alpha1/generated.pb.go
+++ b/pkg/apis/stats/v1alpha1/generated.pb.go
@@ -152,10 +152,66 @@ func (m *AntreaNetworkPolicyStatsList) XXX_DiscardUnknown() {
 
 var xxx_messageInfo_AntreaNetworkPolicyStatsList proto.InternalMessageInfo
 
+func (m *MulticastGroup) Reset()      { *m = MulticastGroup{} }
+func (*MulticastGroup) ProtoMessage() {}
+func (*MulticastGroup) Descriptor() ([]byte, []int) {
+	return fileDescriptor_91b517c6fa558473, []int{4}
+}
+func (m *MulticastGroup) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *MulticastGroup) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *MulticastGroup) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_MulticastGroup.Merge(m, src)
+}
+func (m *MulticastGroup) XXX_Size() int {
+	return m.Size()
+}
+func (m *MulticastGroup) XXX_DiscardUnknown() {
+	xxx_messageInfo_MulticastGroup.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MulticastGroup proto.InternalMessageInfo
+
+func (m *MulticastGroupList) Reset()      { *m = MulticastGroupList{} }
+func (*MulticastGroupList) ProtoMessage() {}
+func (*MulticastGroupList) Descriptor() ([]byte, []int) {
+	return fileDescriptor_91b517c6fa558473, []int{5}
+}
+func (m *MulticastGroupList) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *MulticastGroupList) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *MulticastGroupList) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_MulticastGroupList.Merge(m, src)
+}
+func (m *MulticastGroupList) XXX_Size() int {
+	return m.Size()
+}
+func (m *MulticastGroupList) XXX_DiscardUnknown() {
+	xxx_messageInfo_MulticastGroupList.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MulticastGroupList proto.InternalMessageInfo
+
 func (m *NetworkPolicyStats) Reset()      { *m = NetworkPolicyStats{} }
 func (*NetworkPolicyStats) ProtoMessage() {}
 func (*NetworkPolicyStats) Descriptor() ([]byte, []int) {
-	return fileDescriptor_91b517c6fa558473, []int{4}
+	return fileDescriptor_91b517c6fa558473, []int{6}
 }
 func (m *NetworkPolicyStats) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -183,7 +239,7 @@ var xxx_messageInfo_NetworkPolicyStats proto.InternalMessageInfo
 func (m *NetworkPolicyStatsList) Reset()      { *m = NetworkPolicyStatsList{} }
 func (*NetworkPolicyStatsList) ProtoMessage() {}
 func (*NetworkPolicyStatsList) Descriptor() ([]byte, []int) {
-	return fileDescriptor_91b517c6fa558473, []int{5}
+	return fileDescriptor_91b517c6fa558473, []int{7}
 }
 func (m *NetworkPolicyStatsList) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -208,10 +264,38 @@ func (m *NetworkPolicyStatsList) XXX_DiscardUnknown() {
 
 var xxx_messageInfo_NetworkPolicyStatsList proto.InternalMessageInfo
 
+func (m *PodReference) Reset()      { *m = PodReference{} }
+func (*PodReference) ProtoMessage() {}
+func (*PodReference) Descriptor() ([]byte, []int) {
+	return fileDescriptor_91b517c6fa558473, []int{8}
+}
+func (m *PodReference) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *PodReference) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *PodReference) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_PodReference.Merge(m, src)
+}
+func (m *PodReference) XXX_Size() int {
+	return m.Size()
+}
+func (m *PodReference) XXX_DiscardUnknown() {
+	xxx_messageInfo_PodReference.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PodReference proto.InternalMessageInfo
+
 func (m *RuleTrafficStats) Reset()      { *m = RuleTrafficStats{} }
 func (*RuleTrafficStats) ProtoMessage() {}
 func (*RuleTrafficStats) Descriptor() ([]byte, []int) {
-	return fileDescriptor_91b517c6fa558473, []int{6}
+	return fileDescriptor_91b517c6fa558473, []int{9}
 }
 func (m *RuleTrafficStats) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -239,7 +323,7 @@ var xxx_messageInfo_RuleTrafficStats proto.InternalMessageInfo
 func (m *TrafficStats) Reset()      { *m = TrafficStats{} }
 func (*TrafficStats) ProtoMessage() {}
 func (*TrafficStats) Descriptor() ([]byte, []int) {
-	return fileDescriptor_91b517c6fa558473, []int{7}
+	return fileDescriptor_91b517c6fa558473, []int{10}
 }
 func (m *TrafficStats) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -269,8 +353,11 @@ func init() {
 	proto.RegisterType((*AntreaClusterNetworkPolicyStatsList)(nil), "antrea_io.antrea.pkg.apis.stats.v1alpha1.AntreaClusterNetworkPolicyStatsList")
 	proto.RegisterType((*AntreaNetworkPolicyStats)(nil), "antrea_io.antrea.pkg.apis.stats.v1alpha1.AntreaNetworkPolicyStats")
 	proto.RegisterType((*AntreaNetworkPolicyStatsList)(nil), "antrea_io.antrea.pkg.apis.stats.v1alpha1.AntreaNetworkPolicyStatsList")
+	proto.RegisterType((*MulticastGroup)(nil), "antrea_io.antrea.pkg.apis.stats.v1alpha1.MulticastGroup")
+	proto.RegisterType((*MulticastGroupList)(nil), "antrea_io.antrea.pkg.apis.stats.v1alpha1.MulticastGroupList")
 	proto.RegisterType((*NetworkPolicyStats)(nil), "antrea_io.antrea.pkg.apis.stats.v1alpha1.NetworkPolicyStats")
 	proto.RegisterType((*NetworkPolicyStatsList)(nil), "antrea_io.antrea.pkg.apis.stats.v1alpha1.NetworkPolicyStatsList")
+	proto.RegisterType((*PodReference)(nil), "antrea_io.antrea.pkg.apis.stats.v1alpha1.PodReference")
 	proto.RegisterType((*RuleTrafficStats)(nil), "antrea_io.antrea.pkg.apis.stats.v1alpha1.RuleTrafficStats")
 	proto.RegisterType((*TrafficStats)(nil), "antrea_io.antrea.pkg.apis.stats.v1alpha1.TrafficStats")
 }
@@ -280,44 +367,51 @@ func init() {
 }
 
 var fileDescriptor_91b517c6fa558473 = []byte{
-	// 592 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x56, 0xcf, 0x6b, 0x13, 0x41,
-	0x14, 0xce, 0x24, 0x0d, 0x8d, 0xd3, 0x88, 0x61, 0x10, 0x09, 0x41, 0x36, 0x21, 0xbd, 0x44, 0xd0,
-	0x59, 0x53, 0xa4, 0x14, 0xf1, 0xe2, 0x7a, 0x2a, 0x68, 0x2c, 0x5b, 0x4f, 0x22, 0xe8, 0x64, 0x3b,
-	0xd9, 0x8c, 0xc9, 0xee, 0x2c, 0x3b, 0x93, 0x48, 0x6e, 0xfd, 0x03, 0x3c, 0xf8, 0x57, 0xf8, 0xb7,
-	0xe4, 0xd8, 0x63, 0xbd, 0x14, 0xb3, 0x22, 0x78, 0x15, 0x2f, 0x1e, 0x65, 0x66, 0x37, 0xbf, 0x29,
-	0x59, 0x2f, 0xed, 0x41, 0x6f, 0x3b, 0xef, 0xbd, 0xef, 0x7d, 0xef, 0x7d, 0xef, 0x23, 0x04, 0x1e,
-	0x10, 0x5f, 0x86, 0x94, 0x60, 0xc6, 0xcd, 0xf8, 0xcb, 0x0c, 0x7a, 0xae, 0x49, 0x02, 0x26, 0x4c,
-	0x21, 0x89, 0x14, 0xe6, 0xb0, 0x49, 0xfa, 0x41, 0x97, 0x34, 0x4d, 0x97, 0xfa, 0x34, 0x24, 0x92,
-	0x9e, 0xe0, 0x20, 0xe4, 0x92, 0xa3, 0x46, 0x5c, 0xff, 0x96, 0x71, 0x9c, 0xf4, 0x08, 0x7a, 0x2e,
-	0x56, 0x48, 0xac, 0x91, 0x78, 0x8a, 0xac, 0x3c, 0x70, 0x99, 0xec, 0x0e, 0xda, 0xd8, 0xe1, 0x9e,
-	0xe9, 0x72, 0x97, 0x9b, 0xba, 0x41, 0x7b, 0xd0, 0xd1, 0x2f, 0xfd, 0xd0, 0x5f, 0x71, 0xe3, 0xca,
-	0xa3, 0xde, 0x81, 0xd0, 0xf3, 0x04, 0xcc, 0x23, 0x4e, 0x97, 0xf9, 0x34, 0x1c, 0xcd, 0xa7, 0xf2,
-	0xa8, 0x24, 0xe6, 0x70, 0x6d, 0x9c, 0x8a, 0x79, 0x19, 0x2a, 0x1c, 0xf8, 0x92, 0x79, 0x74, 0x0d,
-	0xb0, 0xbf, 0x09, 0x20, 0x9c, 0x2e, 0xf5, 0xc8, 0x2a, 0xae, 0xfe, 0x3b, 0x0b, 0xab, 0x4f, 0xf5,
-	0xc2, 0xcf, 0xfa, 0x03, 0x21, 0x69, 0xd8, 0xa2, 0xf2, 0x03, 0x0f, 0x7b, 0x47, 0xbc, 0xcf, 0x9c,
-	0xd1, 0xb1, 0x5a, 0x1d, 0xbd, 0x83, 0x05, 0x35, 0xe7, 0x09, 0x91, 0xa4, 0x0c, 0x6a, 0xa0, 0xb1,
-	0xb3, 0xf7, 0x10, 0xc7, 0x74, 0x78, 0x91, 0x6e, 0xae, 0x98, 0xaa, 0xc6, 0xc3, 0x26, 0x7e, 0xd9,
-	0x7e, 0x4f, 0x1d, 0xf9, 0x82, 0x4a, 0x62, 0xa1, 0xf1, 0x45, 0x35, 0x13, 0x5d, 0x54, 0xe1, 0x3c,
-	0x66, 0xcf, 0xba, 0xa2, 0x00, 0x16, 0x65, 0x48, 0x3a, 0x1d, 0xe6, 0x68, 0xc6, 0x72, 0x56, 0xb3,
-	0xec, 0xe3, 0xb4, 0x47, 0xc1, 0xaf, 0x16, 0xd0, 0xd6, 0xed, 0x84, 0xab, 0xb8, 0x18, 0xb5, 0x97,
-	0x18, 0xd0, 0x29, 0x80, 0xa5, 0x70, 0xd0, 0xa7, 0x8b, 0x25, 0xe5, 0x5c, 0x2d, 0xd7, 0xd8, 0xd9,
-	0x7b, 0x9c, 0x9e, 0xd6, 0x5e, 0xe9, 0x60, 0x95, 0x13, 0xea, 0xd2, 0x6a, 0xc6, 0x5e, 0x63, 0xab,
-	0xff, 0x02, 0x70, 0x77, 0x83, 0xf4, 0xcf, 0x99, 0x90, 0xe8, 0xcd, 0x9a, 0xfc, 0x38, 0x9d, 0xfc,
-	0x0a, 0xad, 0xc5, 0x2f, 0x25, 0x53, 0x15, 0xa6, 0x91, 0x05, 0xe9, 0x7d, 0x98, 0x67, 0x92, 0x7a,
-	0x4a, 0x73, 0xb5, 0xfc, 0x61, 0xfa, 0xe5, 0x37, 0xcc, 0x6e, 0xdd, 0x4c, 0x58, 0xf3, 0x87, 0xaa,
-	0xbf, 0x1d, 0xd3, 0xd4, 0x7f, 0x66, 0x61, 0x39, 0x46, 0xfe, 0x77, 0xda, 0x55, 0x39, 0xed, 0x3b,
-	0x80, 0x77, 0x2f, 0xd3, 0xfc, 0x0a, 0x2c, 0xe6, 0x2e, 0x5b, 0xcc, 0xfa, 0x5b, 0x8b, 0xa5, 0xf6,
-	0xd6, 0x0f, 0x00, 0xd1, 0xbf, 0xe1, 0xaa, 0xfa, 0x17, 0x00, 0xef, 0x5c, 0xcb, 0x31, 0xc9, 0xf2,
-	0x31, 0x9f, 0xa4, 0xdf, 0x31, 0xf5, 0x19, 0x3f, 0x03, 0xb8, 0xe6, 0x6a, 0x54, 0x83, 0x5b, 0x3e,
-	0xf1, 0xa8, 0xde, 0xe8, 0x86, 0x55, 0x4c, 0x80, 0x5b, 0x2d, 0xe2, 0x51, 0x5b, 0x67, 0xae, 0xe1,
-	0x08, 0x1f, 0x01, 0x5c, 0x4a, 0xa3, 0x7b, 0x70, 0x3b, 0x20, 0x4e, 0x8f, 0x4a, 0xa1, 0xe7, 0xcc,
-	0x59, 0xb7, 0x92, 0x2e, 0xdb, 0x47, 0x71, 0xd8, 0x9e, 0xe6, 0xd1, 0x2e, 0xcc, 0xb7, 0x47, 0x92,
-	0xc6, 0x63, 0xe6, 0xe6, 0x4a, 0x58, 0x2a, 0x68, 0xc7, 0x39, 0x74, 0x1f, 0x16, 0x04, 0x15, 0x82,
-	0x71, 0x5f, 0xfd, 0x64, 0xa8, 0xba, 0xd9, 0x69, 0x8e, 0x93, 0xb8, 0x3d, 0xab, 0xb0, 0x5a, 0xe3,
-	0x89, 0x91, 0x39, 0x9b, 0x18, 0x99, 0xf3, 0x89, 0x91, 0x39, 0x8d, 0x0c, 0x30, 0x8e, 0x0c, 0x70,
-	0x16, 0x19, 0xe0, 0x3c, 0x32, 0xc0, 0xd7, 0xc8, 0x00, 0x9f, 0xbe, 0x19, 0x99, 0xd7, 0x8d, 0xb4,
-	0xff, 0x91, 0xfe, 0x04, 0x00, 0x00, 0xff, 0xff, 0x82, 0xba, 0xaa, 0x57, 0x4e, 0x09, 0x00, 0x00,
+	// 704 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x56, 0x4f, 0x6b, 0x13, 0x4d,
+	0x18, 0xcf, 0x34, 0x2d, 0x6d, 0xa6, 0x79, 0xdf, 0xb7, 0xef, 0x20, 0x12, 0x8a, 0x6c, 0x4b, 0x7a,
+	0x89, 0xa0, 0xb3, 0xb6, 0x48, 0x29, 0xe2, 0xc5, 0xf5, 0x20, 0x05, 0x1b, 0xc3, 0xd4, 0x83, 0x88,
+	0xa2, 0x93, 0xcd, 0x64, 0x33, 0x26, 0xbb, 0xb3, 0xec, 0xcc, 0x56, 0x7a, 0xeb, 0x07, 0xf0, 0xe0,
+	0xa7, 0xf0, 0xb3, 0xf4, 0x58, 0x6f, 0xf5, 0x52, 0x6c, 0x44, 0xf0, 0x2a, 0x5e, 0x3c, 0xca, 0xcc,
+	0x6e, 0xba, 0xd9, 0x86, 0xd2, 0xed, 0x25, 0x1e, 0xf4, 0x94, 0x9d, 0xe7, 0xdf, 0xef, 0xf7, 0x3c,
+	0xcf, 0x6f, 0x86, 0xc0, 0x2d, 0x1a, 0xa8, 0x88, 0x51, 0xcc, 0x85, 0x9d, 0x7c, 0xd9, 0x61, 0xdf,
+	0xb3, 0x69, 0xc8, 0xa5, 0x2d, 0x15, 0x55, 0xd2, 0xde, 0x5b, 0xa7, 0x83, 0xb0, 0x47, 0xd7, 0x6d,
+	0x8f, 0x05, 0x2c, 0xa2, 0x8a, 0x75, 0x70, 0x18, 0x09, 0x25, 0x50, 0x23, 0x89, 0x7f, 0xc5, 0x05,
+	0x4e, 0x6b, 0x84, 0x7d, 0x0f, 0xeb, 0x4c, 0x6c, 0x32, 0xf1, 0x28, 0x73, 0xf9, 0xb6, 0xc7, 0x55,
+	0x2f, 0x6e, 0x63, 0x57, 0xf8, 0xb6, 0x27, 0x3c, 0x61, 0x9b, 0x02, 0xed, 0xb8, 0x6b, 0x4e, 0xe6,
+	0x60, 0xbe, 0x92, 0xc2, 0xcb, 0x77, 0xfb, 0x5b, 0xd2, 0xf0, 0x09, 0xb9, 0x4f, 0xdd, 0x1e, 0x0f,
+	0x58, 0xb4, 0x9f, 0xb1, 0xf2, 0x99, 0xa2, 0xf6, 0xde, 0x04, 0x9d, 0x65, 0xfb, 0xa2, 0xac, 0x28,
+	0x0e, 0x14, 0xf7, 0xd9, 0x44, 0xc2, 0xe6, 0x65, 0x09, 0xd2, 0xed, 0x31, 0x9f, 0x9e, 0xcf, 0xab,
+	0xff, 0x9c, 0x81, 0x2b, 0x0f, 0x4c, 0xc3, 0x0f, 0x07, 0xb1, 0x54, 0x2c, 0x6a, 0x32, 0xf5, 0x56,
+	0x44, 0xfd, 0x96, 0x18, 0x70, 0x77, 0x7f, 0x57, 0xb7, 0x8e, 0x5e, 0xc3, 0x05, 0xcd, 0xb3, 0x43,
+	0x15, 0xad, 0x81, 0x55, 0xd0, 0x58, 0xdc, 0xb8, 0x83, 0x13, 0x38, 0x3c, 0x0e, 0x97, 0x4d, 0x4c,
+	0x47, 0xe3, 0xbd, 0x75, 0xfc, 0xa4, 0xfd, 0x86, 0xb9, 0x6a, 0x87, 0x29, 0xea, 0xa0, 0xc3, 0x93,
+	0x95, 0xd2, 0xf0, 0x64, 0x05, 0x66, 0x36, 0x72, 0x56, 0x15, 0x85, 0xb0, 0xaa, 0x22, 0xda, 0xed,
+	0x72, 0xd7, 0x20, 0xd6, 0x66, 0x0c, 0xca, 0x26, 0x2e, 0xba, 0x14, 0xfc, 0x74, 0x2c, 0xdb, 0xb9,
+	0x96, 0x62, 0x55, 0xc7, 0xad, 0x24, 0x87, 0x80, 0x0e, 0x00, 0x5c, 0x8a, 0xe2, 0x01, 0x1b, 0x0f,
+	0xa9, 0x95, 0x57, 0xcb, 0x8d, 0xc5, 0x8d, 0x7b, 0xc5, 0x61, 0xc9, 0xb9, 0x0a, 0x4e, 0x2d, 0x85,
+	0x5e, 0x3a, 0xef, 0x21, 0x13, 0x68, 0xf5, 0x1f, 0x00, 0xae, 0x5d, 0x32, 0xfa, 0xc7, 0x5c, 0x2a,
+	0xf4, 0x62, 0x62, 0xfc, 0xb8, 0xd8, 0xf8, 0x75, 0xb6, 0x19, 0xfe, 0x52, 0xca, 0x6a, 0x61, 0x64,
+	0x19, 0x1b, 0x7d, 0x00, 0xe7, 0xb8, 0x62, 0xbe, 0x9e, 0xb9, 0x6e, 0x7e, 0xbb, 0x78, 0xf3, 0x97,
+	0x70, 0x77, 0xfe, 0x49, 0x51, 0xe7, 0xb6, 0x75, 0x7d, 0x92, 0xc0, 0xd4, 0xbf, 0xcf, 0xc0, 0x5a,
+	0x92, 0xf9, 0x57, 0x69, 0xd3, 0x52, 0xda, 0x57, 0x00, 0x6f, 0x5c, 0x34, 0xf3, 0x29, 0x48, 0xcc,
+	0xcb, 0x4b, 0xcc, 0xb9, 0xaa, 0xc4, 0x8a, 0x6b, 0x0b, 0xc0, 0x7f, 0x77, 0xe2, 0x81, 0xe2, 0x2e,
+	0x95, 0xea, 0x51, 0x24, 0xe2, 0x70, 0x0a, 0x8a, 0x5a, 0x83, 0x73, 0x9e, 0x86, 0x32, 0x52, 0xaa,
+	0x64, 0xcc, 0x0c, 0x3e, 0x49, 0x7c, 0xe8, 0x19, 0x9c, 0x0d, 0x45, 0x67, 0xb4, 0xf7, 0x2b, 0xc8,
+	0xad, 0x25, 0x3a, 0x84, 0x75, 0x59, 0xc4, 0x02, 0x97, 0x39, 0xd5, 0xb4, 0xf6, 0x6c, 0x4b, 0x74,
+	0x24, 0x31, 0x15, 0xeb, 0x1f, 0x01, 0x44, 0xf9, 0x9e, 0xa7, 0xb0, 0xd1, 0x97, 0xf9, 0x8d, 0x6e,
+	0x15, 0xef, 0x27, 0x4f, 0xf5, 0x82, 0x3d, 0x7e, 0x03, 0x10, 0xfd, 0x19, 0xaf, 0x43, 0xfd, 0x13,
+	0x80, 0xd7, 0x7f, 0xcb, 0xa5, 0xa4, 0xf9, 0x15, 0xde, 0x2f, 0xde, 0x63, 0xe1, 0xeb, 0x48, 0x61,
+	0x75, 0x5c, 0xbe, 0x68, 0x15, 0xce, 0x06, 0xd4, 0x67, 0xa6, 0x99, 0x4a, 0x26, 0xe6, 0x26, 0xf5,
+	0x19, 0x31, 0x1e, 0x64, 0xc3, 0x8a, 0xfe, 0x95, 0x21, 0x75, 0x59, 0x7a, 0x9f, 0xfe, 0x4f, 0xc3,
+	0x2a, 0xcd, 0x91, 0x83, 0x64, 0x31, 0xf5, 0x0f, 0x00, 0x4e, 0x3c, 0x80, 0x05, 0x70, 0xa6, 0xbf,
+	0xe7, 0x77, 0x00, 0xe6, 0xdc, 0xe8, 0x26, 0x9c, 0x0f, 0xa9, 0xdb, 0x67, 0x4a, 0x1a, 0x9e, 0x65,
+	0xe7, 0xbf, 0xb4, 0xca, 0x7c, 0x2b, 0x31, 0x93, 0x91, 0x5f, 0xbf, 0x30, 0xed, 0x7d, 0xc5, 0x12,
+	0x9a, 0xe5, 0x6c, 0xd8, 0x8e, 0x36, 0x92, 0xc4, 0x87, 0x6e, 0xc1, 0x05, 0xc9, 0xa4, 0xe4, 0x22,
+	0xd0, 0xaf, 0x8c, 0x8e, 0x3b, 0xdb, 0xfe, 0x6e, 0x6a, 0x27, 0x67, 0x11, 0x4e, 0xf3, 0xf0, 0xd4,
+	0x2a, 0x1d, 0x9d, 0x5a, 0xa5, 0xe3, 0x53, 0xab, 0x74, 0x30, 0xb4, 0xc0, 0xe1, 0xd0, 0x02, 0x47,
+	0x43, 0x0b, 0x1c, 0x0f, 0x2d, 0xf0, 0x79, 0x68, 0x81, 0xf7, 0x5f, 0xac, 0xd2, 0xf3, 0x46, 0xd1,
+	0xbf, 0xd3, 0xbf, 0x02, 0x00, 0x00, 0xff, 0xff, 0x73, 0x1f, 0x1a, 0xcb, 0x79, 0x0b, 0x00, 0x00,
 }
 
 func (m *AntreaClusterNetworkPolicyStats) Marshal() (dAtA []byte, err error) {
@@ -528,6 +622,105 @@ func (m *AntreaNetworkPolicyStatsList) MarshalToSizedBuffer(dAtA []byte) (int, e
 	return len(dAtA) - i, nil
 }
 
+func (m *MulticastGroup) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *MulticastGroup) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MulticastGroup) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if len(m.Pods) > 0 {
+		for iNdEx := len(m.Pods) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.Pods[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintGenerated(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x1a
+		}
+	}
+	i -= len(m.Group)
+	copy(dAtA[i:], m.Group)
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.Group)))
+	i--
+	dAtA[i] = 0x12
+	{
+		size, err := m.ObjectMeta.MarshalToSizedBuffer(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarintGenerated(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
+func (m *MulticastGroupList) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *MulticastGroupList) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MulticastGroupList) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if len(m.Items) > 0 {
+		for iNdEx := len(m.Items) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.Items[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintGenerated(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x12
+		}
+	}
+	{
+		size, err := m.ListMeta.MarshalToSizedBuffer(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarintGenerated(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
 func (m *NetworkPolicyStats) Marshal() (dAtA []byte, err error) {
 	size := m.Size()
 	dAtA = make([]byte, size)
@@ -618,6 +811,39 @@ func (m *NetworkPolicyStatsList) MarshalToSizedBuffer(dAtA []byte) (int, error)
 	return len(dAtA) - i, nil
 }
 
+func (m *PodReference) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *PodReference) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *PodReference) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	i -= len(m.Namespace)
+	copy(dAtA[i:], m.Namespace)
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.Namespace)))
+	i--
+	dAtA[i] = 0x12
+	i -= len(m.Name)
+	copy(dAtA[i:], m.Name)
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name)))
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
 func (m *RuleTrafficStats) Marshal() (dAtA []byte, err error) {
 	size := m.Size()
 	dAtA = make([]byte, size)
@@ -771,6 +997,42 @@ func (m *AntreaNetworkPolicyStatsList) Size() (n int) {
 	return n
 }
 
+func (m *MulticastGroup) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.ObjectMeta.Size()
+	n += 1 + l + sovGenerated(uint64(l))
+	l = len(m.Group)
+	n += 1 + l + sovGenerated(uint64(l))
+	if len(m.Pods) > 0 {
+		for _, e := range m.Pods {
+			l = e.Size()
+			n += 1 + l + sovGenerated(uint64(l))
+		}
+	}
+	return n
+}
+
+func (m *MulticastGroupList) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.ListMeta.Size()
+	n += 1 + l + sovGenerated(uint64(l))
+	if len(m.Items) > 0 {
+		for _, e := range m.Items {
+			l = e.Size()
+			n += 1 + l + sovGenerated(uint64(l))
+		}
+	}
+	return n
+}
+
 func (m *NetworkPolicyStats) Size() (n int) {
 	if m == nil {
 		return 0
@@ -801,6 +1063,19 @@ func (m *NetworkPolicyStatsList) Size() (n int) {
 	return n
 }
 
+func (m *PodReference) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Name)
+	n += 1 + l + sovGenerated(uint64(l))
+	l = len(m.Namespace)
+	n += 1 + l + sovGenerated(uint64(l))
+	return n
+}
+
 func (m *RuleTrafficStats) Size() (n int) {
 	if m == nil {
 		return 0
@@ -898,6 +1173,39 @@ func (this *AntreaNetworkPolicyStatsList) String() string {
 	}, "")
 	return s
 }
+func (this *MulticastGroup) String() string {
+	if this == nil {
+		return "nil"
+	}
+	repeatedStringForPods := "[]PodReference{"
+	for _, f := range this.Pods {
+		repeatedStringForPods += strings.Replace(strings.Replace(f.String(), "PodReference", "PodReference", 1), `&`, ``, 1) + ","
+	}
+	repeatedStringForPods += "}"
+	s := strings.Join([]string{`&MulticastGroup{`,
+		`ObjectMeta:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.ObjectMeta), "ObjectMeta", "v1.ObjectMeta", 1), `&`, ``, 1) + `,`,
+		`Group:` + fmt.Sprintf("%v", this.Group) + `,`,
+		`Pods:` + repeatedStringForPods + `,`,
+		`}`,
+	}, "")
+	return s
+}
+func (this *MulticastGroupList) String() string {
+	if this == nil {
+		return "nil"
+	}
+	repeatedStringForItems := "[]MulticastGroup{"
+	for _, f := range this.Items {
+		repeatedStringForItems += strings.Replace(strings.Replace(f.String(), "MulticastGroup", "MulticastGroup", 1), `&`, ``, 1) + ","
+	}
+	repeatedStringForItems += "}"
+	s := strings.Join([]string{`&MulticastGroupList{`,
+		`ListMeta:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.ListMeta), "ListMeta", "v1.ListMeta", 1), `&`, ``, 1) + `,`,
+		`Items:` + repeatedStringForItems + `,`,
+		`}`,
+	}, "")
+	return s
+}
 func (this *NetworkPolicyStats) String() string {
 	if this == nil {
 		return "nil"
@@ -925,6 +1233,17 @@ func (this *NetworkPolicyStatsList) String() string {
 	}, "")
 	return s
 }
+func (this *PodReference) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&PodReference{`,
+		`Name:` + fmt.Sprintf("%v", this.Name) + `,`,
+		`Namespace:` + fmt.Sprintf("%v", this.Namespace) + `,`,
+		`}`,
+	}, "")
+	return s
+}
 func (this *RuleTrafficStats) String() string {
 	if this == nil {
 		return "nil"
@@ -1490,7 +1809,7 @@ func (m *AntreaNetworkPolicyStatsList) Unmarshal(dAtA []byte) error {
 	}
 	return nil
 }
-func (m *NetworkPolicyStats) Unmarshal(dAtA []byte) error {
+func (m *MulticastGroup) Unmarshal(dAtA []byte) error {
 	l := len(dAtA)
 	iNdEx := 0
 	for iNdEx < l {
@@ -1513,10 +1832,10 @@ func (m *NetworkPolicyStats) Unmarshal(dAtA []byte) error {
 		fieldNum := int32(wire >> 3)
 		wireType := int(wire & 0x7)
 		if wireType == 4 {
-			return fmt.Errorf("proto: NetworkPolicyStats: wiretype end group for non-group")
+			return fmt.Errorf("proto: MulticastGroup: wiretype end group for non-group")
 		}
 		if fieldNum <= 0 {
-			return fmt.Errorf("proto: NetworkPolicyStats: illegal tag %d (wire type %d)", fieldNum, wire)
+			return fmt.Errorf("proto: MulticastGroup: illegal tag %d (wire type %d)", fieldNum, wire)
 		}
 		switch fieldNum {
 		case 1:
@@ -1554,9 +1873,9 @@ func (m *NetworkPolicyStats) Unmarshal(dAtA []byte) error {
 			iNdEx = postIndex
 		case 2:
 			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field TrafficStats", wireType)
+				return fmt.Errorf("proto: wrong wireType = %d for field Group", wireType)
 			}
-			var msglen int
+			var stringLen uint64
 			for shift := uint(0); ; shift += 7 {
 				if shift >= 64 {
 					return ErrIntOverflowGenerated
@@ -1566,23 +1885,289 @@ func (m *NetworkPolicyStats) Unmarshal(dAtA []byte) error {
 				}
 				b := dAtA[iNdEx]
 				iNdEx++
-				msglen |= int(b&0x7F) << shift
+				stringLen |= uint64(b&0x7F) << shift
 				if b < 0x80 {
 					break
 				}
 			}
-			if msglen < 0 {
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
 				return ErrInvalidLengthGenerated
 			}
-			postIndex := iNdEx + msglen
+			postIndex := iNdEx + intStringLen
 			if postIndex < 0 {
 				return ErrInvalidLengthGenerated
 			}
 			if postIndex > l {
 				return io.ErrUnexpectedEOF
 			}
-			if err := m.TrafficStats.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
-				return err
+			m.Group = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Pods", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Pods = append(m.Pods, PodReference{})
+			if err := m.Pods[len(m.Pods)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGenerated(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if (skippy < 0) || (iNdEx+skippy) < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *MulticastGroupList) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGenerated
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: MulticastGroupList: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: MulticastGroupList: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ListMeta", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.ListMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Items = append(m.Items, MulticastGroup{})
+			if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGenerated(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if (skippy < 0) || (iNdEx+skippy) < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *NetworkPolicyStats) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGenerated
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: NetworkPolicyStats: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: NetworkPolicyStats: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ObjectMeta", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.ObjectMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TrafficStats", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.TrafficStats.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
 			}
 			iNdEx = postIndex
 		default:
@@ -1723,6 +2308,120 @@ func (m *NetworkPolicyStatsList) Unmarshal(dAtA []byte) error {
 	}
 	return nil
 }
+func (m *PodReference) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGenerated
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: PodReference: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: PodReference: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Name = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Namespace", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Namespace = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGenerated(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if (skippy < 0) || (iNdEx+skippy) < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
 func (m *RuleTrafficStats) Unmarshal(dAtA []byte) error {
 	l := len(dAtA)
 	iNdEx := 0
diff --git a/pkg/apis/stats/v1alpha1/generated.proto b/pkg/apis/stats/v1alpha1/generated.proto
index 70f0d216c..dd18b35de 100644
--- a/pkg/apis/stats/v1alpha1/generated.proto
+++ b/pkg/apis/stats/v1alpha1/generated.proto
@@ -63,6 +63,25 @@ message AntreaNetworkPolicyStatsList {
   repeated AntreaNetworkPolicyStats items = 2;
 }
 
+// MulticastGroup contains the mapping between multicast group and Pods.
+message MulticastGroup {
+  optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1;
+
+  // Group is the IP of the multicast group.
+  optional string group = 2;
+
+  // Pods is the list of Pods that have joined the multicast group.
+  repeated PodReference pods = 3;
+}
+
+// MulticastGroupList is a list of MulticastGroup.
+message MulticastGroupList {
+  optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1;
+
+  // List of MulticastGroup.
+  repeated MulticastGroup items = 2;
+}
+
 // NetworkPolicyStats is the statistics of a K8s NetworkPolicy.
 message NetworkPolicyStats {
   optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1;
@@ -79,6 +98,15 @@ message NetworkPolicyStatsList {
   repeated NetworkPolicyStats items = 2;
 }
 
+// PodReference represents a Pod Reference.
+message PodReference {
+  // The name of this Pod.
+  optional string name = 1;
+
+  // The namespace of this Pod.
+  optional string namespace = 2;
+}
+
 // RuleTrafficStats contains TrafficStats of single rule inside a NetworkPolicy.
 message RuleTrafficStats {
   optional string name = 1;
diff --git a/pkg/apis/stats/v1alpha1/register.go b/pkg/apis/stats/v1alpha1/register.go
index 30c40f47f..fcdb90323 100644
--- a/pkg/apis/stats/v1alpha1/register.go
+++ b/pkg/apis/stats/v1alpha1/register.go
@@ -47,6 +47,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
 		&AntreaNetworkPolicyStatsList{},
 		&NetworkPolicyStats{},
 		&NetworkPolicyStatsList{},
+		&MulticastGroup{},
+		&MulticastGroupList{},
 	)
 	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
 	return nil
diff --git a/pkg/apis/stats/v1alpha1/types.go b/pkg/apis/stats/v1alpha1/types.go
index 4189f56f8..c36f63a8a 100644
--- a/pkg/apis/stats/v1alpha1/types.go
+++ b/pkg/apis/stats/v1alpha1/types.go
@@ -85,6 +85,33 @@ type NetworkPolicyStats struct {
 	TrafficStats TrafficStats `json:"trafficStats,omitempty" protobuf:"bytes,2,opt,name=trafficStats"`
 }
 
+// +genclient
+// +genclient:readonly
+// +genclient:nonNamespaced
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// MulticastGroup contains the mapping between multicast group and Pods.
+type MulticastGroup struct {
+	metav1.TypeMeta   `json:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
+
+	// Group is the IP of the multicast group.
+	Group string `json:"group,omitempty" protobuf:"bytes,2,opt,name=group"`
+	// Pods is the list of Pods that have joined the multicast group.
+	Pods []PodReference `json:"pods" protobuf:"bytes,3,rep,name=pods"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// MulticastGroupList is a list of MulticastGroup.
+type MulticastGroupList struct {
+	metav1.TypeMeta `json:",inline"`
+	metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
+
+	// List of MulticastGroup.
+	Items []MulticastGroup `json:"items" protobuf:"bytes,2,rep,name=items"`
+}
+
 // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 
 // NetworkPolicyStatsList is a list of NetworkPolicyStats.
@@ -96,6 +123,14 @@ type NetworkPolicyStatsList struct {
 	Items []NetworkPolicyStats `json:"items" protobuf:"bytes,2,rep,name=items"`
 }
 
+// PodReference represents a Pod Reference.
+type PodReference struct {
+	// The name of this Pod.
+	Name string `json:"name,omitempty" protobuf:"bytes,1,opt,name=name"`
+	// The namespace of this Pod.
+	Namespace string `json:"namespace,omitempty" protobuf:"bytes,2,opt,name=namespace"`
+}
+
 // TrafficStats contains the traffic stats of a NetworkPolicy.
 type TrafficStats struct {
 	// Packets is the packets count hit by the NetworkPolicy.
diff --git a/pkg/apis/stats/v1alpha1/zz_generated.conversion.go b/pkg/apis/stats/v1alpha1/zz_generated.conversion.go
index f2ba8f55d..223acb853 100644
--- a/pkg/apis/stats/v1alpha1/zz_generated.conversion.go
+++ b/pkg/apis/stats/v1alpha1/zz_generated.conversion.go
@@ -1,7 +1,7 @@
 //go:build !ignore_autogenerated
 // +build !ignore_autogenerated
 
-// Copyright 2021 Antrea Authors
+// Copyright 2022 Antrea Authors
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -74,6 +74,26 @@ func RegisterConversions(s *runtime.Scheme) error {
 	}); err != nil {
 		return err
 	}
+	if err := s.AddGeneratedConversionFunc((*MulticastGroup)(nil), (*stats.MulticastGroup)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1alpha1_MulticastGroup_To_stats_MulticastGroup(a.(*MulticastGroup), b.(*stats.MulticastGroup), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*stats.MulticastGroup)(nil), (*MulticastGroup)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_stats_MulticastGroup_To_v1alpha1_MulticastGroup(a.(*stats.MulticastGroup), b.(*MulticastGroup), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*MulticastGroupList)(nil), (*stats.MulticastGroupList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1alpha1_MulticastGroupList_To_stats_MulticastGroupList(a.(*MulticastGroupList), b.(*stats.MulticastGroupList), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*stats.MulticastGroupList)(nil), (*MulticastGroupList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_stats_MulticastGroupList_To_v1alpha1_MulticastGroupList(a.(*stats.MulticastGroupList), b.(*MulticastGroupList), scope)
+	}); err != nil {
+		return err
+	}
 	if err := s.AddGeneratedConversionFunc((*NetworkPolicyStats)(nil), (*stats.NetworkPolicyStats)(nil), func(a, b interface{}, scope conversion.Scope) error {
 		return Convert_v1alpha1_NetworkPolicyStats_To_stats_NetworkPolicyStats(a.(*NetworkPolicyStats), b.(*stats.NetworkPolicyStats), scope)
 	}); err != nil {
@@ -94,6 +114,16 @@ func RegisterConversions(s *runtime.Scheme) error {
 	}); err != nil {
 		return err
 	}
+	if err := s.AddGeneratedConversionFunc((*PodReference)(nil), (*stats.PodReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1alpha1_PodReference_To_stats_PodReference(a.(*PodReference), b.(*stats.PodReference), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*stats.PodReference)(nil), (*PodReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_stats_PodReference_To_v1alpha1_PodReference(a.(*stats.PodReference), b.(*PodReference), scope)
+	}); err != nil {
+		return err
+	}
 	if err := s.AddGeneratedConversionFunc((*RuleTrafficStats)(nil), (*stats.RuleTrafficStats)(nil), func(a, b interface{}, scope conversion.Scope) error {
 		return Convert_v1alpha1_RuleTrafficStats_To_stats_RuleTrafficStats(a.(*RuleTrafficStats), b.(*stats.RuleTrafficStats), scope)
 	}); err != nil {
@@ -217,6 +247,52 @@ func Convert_stats_AntreaNetworkPolicyStatsList_To_v1alpha1_AntreaNetworkPolicyS
 	return autoConvert_stats_AntreaNetworkPolicyStatsList_To_v1alpha1_AntreaNetworkPolicyStatsList(in, out, s)
 }
 
+func autoConvert_v1alpha1_MulticastGroup_To_stats_MulticastGroup(in *MulticastGroup, out *stats.MulticastGroup, s conversion.Scope) error {
+	out.ObjectMeta = in.ObjectMeta
+	out.Group = in.Group
+	out.Pods = *(*[]stats.PodReference)(unsafe.Pointer(&in.Pods))
+	return nil
+}
+
+// Convert_v1alpha1_MulticastGroup_To_stats_MulticastGroup is an autogenerated conversion function.
+func Convert_v1alpha1_MulticastGroup_To_stats_MulticastGroup(in *MulticastGroup, out *stats.MulticastGroup, s conversion.Scope) error {
+	return autoConvert_v1alpha1_MulticastGroup_To_stats_MulticastGroup(in, out, s)
+}
+
+func autoConvert_stats_MulticastGroup_To_v1alpha1_MulticastGroup(in *stats.MulticastGroup, out *MulticastGroup, s conversion.Scope) error {
+	out.ObjectMeta = in.ObjectMeta
+	out.Group = in.Group
+	out.Pods = *(*[]PodReference)(unsafe.Pointer(&in.Pods))
+	return nil
+}
+
+// Convert_stats_MulticastGroup_To_v1alpha1_MulticastGroup is an autogenerated conversion function.
+func Convert_stats_MulticastGroup_To_v1alpha1_MulticastGroup(in *stats.MulticastGroup, out *MulticastGroup, s conversion.Scope) error {
+	return autoConvert_stats_MulticastGroup_To_v1alpha1_MulticastGroup(in, out, s)
+}
+
+func autoConvert_v1alpha1_MulticastGroupList_To_stats_MulticastGroupList(in *MulticastGroupList, out *stats.MulticastGroupList, s conversion.Scope) error {
+	out.ListMeta = in.ListMeta
+	out.Items = *(*[]stats.MulticastGroup)(unsafe.Pointer(&in.Items))
+	return nil
+}
+
+// Convert_v1alpha1_MulticastGroupList_To_stats_MulticastGroupList is an autogenerated conversion function.
+func Convert_v1alpha1_MulticastGroupList_To_stats_MulticastGroupList(in *MulticastGroupList, out *stats.MulticastGroupList, s conversion.Scope) error {
+	return autoConvert_v1alpha1_MulticastGroupList_To_stats_MulticastGroupList(in, out, s)
+}
+
+func autoConvert_stats_MulticastGroupList_To_v1alpha1_MulticastGroupList(in *stats.MulticastGroupList, out *MulticastGroupList, s conversion.Scope) error {
+	out.ListMeta = in.ListMeta
+	out.Items = *(*[]MulticastGroup)(unsafe.Pointer(&in.Items))
+	return nil
+}
+
+// Convert_stats_MulticastGroupList_To_v1alpha1_MulticastGroupList is an autogenerated conversion function.
+func Convert_stats_MulticastGroupList_To_v1alpha1_MulticastGroupList(in *stats.MulticastGroupList, out *MulticastGroupList, s conversion.Scope) error {
+	return autoConvert_stats_MulticastGroupList_To_v1alpha1_MulticastGroupList(in, out, s)
+}
+
 func autoConvert_v1alpha1_NetworkPolicyStats_To_stats_NetworkPolicyStats(in *NetworkPolicyStats, out *stats.NetworkPolicyStats, s conversion.Scope) error {
 	out.ObjectMeta = in.ObjectMeta
 	if err := Convert_v1alpha1_TrafficStats_To_stats_TrafficStats(&in.TrafficStats, &out.TrafficStats, s); err != nil {
@@ -265,6 +341,28 @@ func Convert_stats_NetworkPolicyStatsList_To_v1alpha1_NetworkPolicyStatsList(in
 	return autoConvert_stats_NetworkPolicyStatsList_To_v1alpha1_NetworkPolicyStatsList(in, out, s)
 }
 
+func autoConvert_v1alpha1_PodReference_To_stats_PodReference(in *PodReference, out *stats.PodReference, s conversion.Scope) error {
+	out.Name = in.Name
+	out.Namespace = in.Namespace
+	return nil
+}
+
+// Convert_v1alpha1_PodReference_To_stats_PodReference is an autogenerated conversion function.
+func Convert_v1alpha1_PodReference_To_stats_PodReference(in *PodReference, out *stats.PodReference, s conversion.Scope) error {
+	return autoConvert_v1alpha1_PodReference_To_stats_PodReference(in, out, s)
+}
+
+func autoConvert_stats_PodReference_To_v1alpha1_PodReference(in *stats.PodReference, out *PodReference, s conversion.Scope) error {
+	out.Name = in.Name
+	out.Namespace = in.Namespace
+	return nil
+}
+
+// Convert_stats_PodReference_To_v1alpha1_PodReference is an autogenerated conversion function.
+func Convert_stats_PodReference_To_v1alpha1_PodReference(in *stats.PodReference, out *PodReference, s conversion.Scope) error {
+	return autoConvert_stats_PodReference_To_v1alpha1_PodReference(in, out, s)
+}
+
 func autoConvert_v1alpha1_RuleTrafficStats_To_stats_RuleTrafficStats(in *RuleTrafficStats, out *stats.RuleTrafficStats, s conversion.Scope) error {
 	out.Name = in.Name
 	if err := Convert_v1alpha1_TrafficStats_To_stats_TrafficStats(&in.TrafficStats, &out.TrafficStats, s); err != nil {
diff --git a/pkg/apis/stats/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/stats/v1alpha1/zz_generated.deepcopy.go
index c5684b4d8..d1c3417a3 100644
--- a/pkg/apis/stats/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/stats/v1alpha1/zz_generated.deepcopy.go
@@ -1,7 +1,7 @@
 //go:build !ignore_autogenerated
 // +build !ignore_autogenerated
 
-// Copyright 2021 Antrea Authors
+// Copyright 2022 Antrea Authors
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -153,6 +153,70 @@ func (in *AntreaNetworkPolicyStatsList) DeepCopyObject() runtime.Object {
 	return nil
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *MulticastGroup) DeepCopyInto(out *MulticastGroup) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	if in.Pods != nil {
+		in, out := &in.Pods, &out.Pods
+		*out = make([]PodReference, len(*in))
+		copy(*out, *in)
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MulticastGroup.
+func (in *MulticastGroup) DeepCopy() *MulticastGroup {
+	if in == nil {
+		return nil
+	}
+	out := new(MulticastGroup)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *MulticastGroup) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *MulticastGroupList) DeepCopyInto(out *MulticastGroupList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]MulticastGroup, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MulticastGroupList.
+func (in *MulticastGroupList) DeepCopy() *MulticastGroupList {
+	if in == nil {
+		return nil
+	}
+	out := new(MulticastGroupList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *MulticastGroupList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *NetworkPolicyStats) DeepCopyInto(out *NetworkPolicyStats) {
 	*out = *in
@@ -213,6 +277,22 @@ func (in *NetworkPolicyStatsList) DeepCopyObject() runtime.Object {
 	return nil
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *PodReference) DeepCopyInto(out *PodReference) {
+	*out = *in
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodReference.
+func (in *PodReference) DeepCopy() *PodReference {
+	if in == nil {
+		return nil
+	}
+	out := new(PodReference)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *RuleTrafficStats) DeepCopyInto(out *RuleTrafficStats) {
 	*out = *in
diff --git a/pkg/apis/stats/zz_generated.deepcopy.go b/pkg/apis/stats/zz_generated.deepcopy.go
index 79273b682..88b296afe 100644
--- a/pkg/apis/stats/zz_generated.deepcopy.go
+++ b/pkg/apis/stats/zz_generated.deepcopy.go
@@ -1,7 +1,7 @@
 //go:build !ignore_autogenerated
 // +build !ignore_autogenerated
 
-// Copyright 2021 Antrea Authors
+// Copyright 2022 Antrea Authors
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -153,6 +153,70 @@ func (in *AntreaNetworkPolicyStatsList) DeepCopyObject() runtime.Object {
 	return nil
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *MulticastGroup) DeepCopyInto(out *MulticastGroup) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	if in.Pods != nil {
+		in, out := &in.Pods, &out.Pods
+		*out = make([]PodReference, len(*in))
+		copy(*out, *in)
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MulticastGroup.
+func (in *MulticastGroup) DeepCopy() *MulticastGroup {
+	if in == nil {
+		return nil
+	}
+	out := new(MulticastGroup)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *MulticastGroup) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *MulticastGroupList) DeepCopyInto(out *MulticastGroupList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]MulticastGroup, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MulticastGroupList.
+func (in *MulticastGroupList) DeepCopy() *MulticastGroupList {
+	if in == nil {
+		return nil
+	}
+	out := new(MulticastGroupList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *MulticastGroupList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *NetworkPolicyStats) DeepCopyInto(out *NetworkPolicyStats) {
 	*out = *in
@@ -213,6 +277,22 @@ func (in *NetworkPolicyStatsList) DeepCopyObject() runtime.Object {
 	return nil
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *PodReference) DeepCopyInto(out *PodReference) {
+	*out = *in
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodReference.
+func (in *PodReference) DeepCopy() *PodReference {
+	if in == nil {
+		return nil
+	}
+	out := new(PodReference)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *RuleTrafficStats) DeepCopyInto(out *RuleTrafficStats) {
 	*out = *in
diff --git a/pkg/apiserver/openapi/zz_generated.openapi.go b/pkg/apiserver/openapi/zz_generated.openapi.go
index fac727bb2..ae42535cc 100644
--- a/pkg/apiserver/openapi/zz_generated.openapi.go
+++ b/pkg/apiserver/openapi/zz_generated.openapi.go
@@ -46,6 +46,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
 		"antrea.io/antrea/pkg/apis/controlplane/v1beta2.GroupReference":                schema_pkg_apis_controlplane_v1beta2_GroupReference(ref),
 		"antrea.io/antrea/pkg/apis/controlplane/v1beta2.IPBlock":                       schema_pkg_apis_controlplane_v1beta2_IPBlock(ref),
 		"antrea.io/antrea/pkg/apis/controlplane/v1beta2.IPNet":                         schema_pkg_apis_controlplane_v1beta2_IPNet(ref),
+		"antrea.io/antrea/pkg/apis/controlplane/v1beta2.MulticastGroupInfo":            schema_pkg_apis_controlplane_v1beta2_MulticastGroupInfo(ref),
 		"antrea.io/antrea/pkg/apis/controlplane/v1beta2.NamedPort":                     schema_pkg_apis_controlplane_v1beta2_NamedPort(ref),
 		"antrea.io/antrea/pkg/apis/controlplane/v1beta2.NetworkPolicy":                 schema_pkg_apis_controlplane_v1beta2_NetworkPolicy(ref),
 		"antrea.io/antrea/pkg/apis/controlplane/v1beta2.NetworkPolicyList":             schema_pkg_apis_controlplane_v1beta2_NetworkPolicyList(ref),
@@ -73,8 +74,11 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
 		"antrea.io/antrea/pkg/apis/stats/v1alpha1.AntreaClusterNetworkPolicyStatsList": schema_pkg_apis_stats_v1alpha1_AntreaClusterNetworkPolicyStatsList(ref),
 		"antrea.io/antrea/pkg/apis/stats/v1alpha1.AntreaNetworkPolicyStats":            schema_pkg_apis_stats_v1alpha1_AntreaNetworkPolicyStats(ref),
 		"antrea.io/antrea/pkg/apis/stats/v1alpha1.AntreaNetworkPolicyStatsList":        schema_pkg_apis_stats_v1alpha1_AntreaNetworkPolicyStatsList(ref),
+		"antrea.io/antrea/pkg/apis/stats/v1alpha1.MulticastGroup":                      schema_pkg_apis_stats_v1alpha1_MulticastGroup(ref),
+		"antrea.io/antrea/pkg/apis/stats/v1alpha1.MulticastGroupList":                  schema_pkg_apis_stats_v1alpha1_MulticastGroupList(ref),
 		"antrea.io/antrea/pkg/apis/stats/v1alpha1.NetworkPolicyStats":                  schema_pkg_apis_stats_v1alpha1_NetworkPolicyStats(ref),
 		"antrea.io/antrea/pkg/apis/stats/v1alpha1.NetworkPolicyStatsList":              schema_pkg_apis_stats_v1alpha1_NetworkPolicyStatsList(ref),
+		"antrea.io/antrea/pkg/apis/stats/v1alpha1.PodReference":                        schema_pkg_apis_stats_v1alpha1_PodReference(ref),
 		"antrea.io/antrea/pkg/apis/stats/v1alpha1.RuleTrafficStats":                    schema_pkg_apis_stats_v1alpha1_RuleTrafficStats(ref),
 		"antrea.io/antrea/pkg/apis/stats/v1alpha1.TrafficStats":                        schema_pkg_apis_stats_v1alpha1_TrafficStats(ref),
 		"antrea.io/antrea/pkg/apis/system/v1beta1.SupportBundle":                       schema_pkg_apis_system_v1beta1_SupportBundle(ref),
@@ -1126,6 +1130,42 @@ func schema_pkg_apis_controlplane_v1beta2_IPNet(ref common.ReferenceCallback) co
 	}
 }
 
+func schema_pkg_apis_controlplane_v1beta2_MulticastGroupInfo(ref common.ReferenceCallback) common.OpenAPIDefinition {
+	return common.OpenAPIDefinition{
+		Schema: spec.Schema{
+			SchemaProps: spec.SchemaProps{
+				Description: "MulticastGroupInfo contains the list of Pods that have joined a multicast group, for a given Node.",
+				Type:        []string{"object"},
+				Properties: map[string]spec.Schema{
+					"group": {
+						SchemaProps: spec.SchemaProps{
+							Description: "Group is the IP of the multicast group.",
+							Type:        []string{"string"},
+							Format:      "",
+						},
+					},
+					"pods": {
+						SchemaProps: spec.SchemaProps{
+							Description: "Pods is the list of Pods that have joined the multicast group.",
+							Type:        []string{"array"},
+							Items: &spec.SchemaOrArray{
+								Schema: &spec.Schema{
+									SchemaProps: spec.SchemaProps{
+										Default: map[string]interface{}{},
+										Ref:     ref("antrea.io/antrea/pkg/apis/controlplane/v1beta2.PodReference"),
+									},
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		Dependencies: []string{
+			"antrea.io/antrea/pkg/apis/controlplane/v1beta2.PodReference"},
+	}
+}
+
 func schema_pkg_apis_controlplane_v1beta2_NamedPort(ref common.ReferenceCallback) common.OpenAPIDefinition {
 	return common.OpenAPIDefinition{
 		Schema: spec.Schema{
@@ -1709,11 +1749,25 @@ func schema_pkg_apis_controlplane_v1beta2_NodeStatsSummary(ref common.ReferenceC
 							},
 						},
 					},
+					"multicast": {
+						SchemaProps: spec.SchemaProps{
+							Description: "Multicast group information collected from the Node.",
+							Type:        []string{"array"},
+							Items: &spec.SchemaOrArray{
+								Schema: &spec.Schema{
+									SchemaProps: spec.SchemaProps{
+										Default: map[string]interface{}{},
+										Ref:     ref("antrea.io/antrea/pkg/apis/controlplane/v1beta2.MulticastGroupInfo"),
+									},
+								},
+							},
+						},
+					},
 				},
 			},
 		},
 		Dependencies: []string{
-			"antrea.io/antrea/pkg/apis/controlplane/v1beta2.NetworkPolicyStats", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
+			"antrea.io/antrea/pkg/apis/controlplane/v1beta2.MulticastGroupInfo", "antrea.io/antrea/pkg/apis/controlplane/v1beta2.NetworkPolicyStats", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
 	}
 }
 
@@ -2546,6 +2600,113 @@ func schema_pkg_apis_stats_v1alpha1_AntreaNetworkPolicyStatsList(ref common.Refe
 	}
 }
 
+func schema_pkg_apis_stats_v1alpha1_MulticastGroup(ref common.ReferenceCallback) common.OpenAPIDefinition {
+	return common.OpenAPIDefinition{
+		Schema: spec.Schema{
+			SchemaProps: spec.SchemaProps{
+				Description: "MulticastGroup contains the mapping between multicast group and Pods.",
+				Type:        []string{"object"},
+				Properties: map[string]spec.Schema{
+					"kind": {
+						SchemaProps: spec.SchemaProps{
+							Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+							Type:        []string{"string"},
+							Format:      "",
+						},
+					},
+					"apiVersion": {
+						SchemaProps: spec.SchemaProps{
+							Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+							Type:        []string{"string"},
+							Format:      "",
+						},
+					},
+					"metadata": {
+						SchemaProps: spec.SchemaProps{
+							Default: map[string]interface{}{},
+							Ref:     ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
+						},
+					},
+					"group": {
+						SchemaProps: spec.SchemaProps{
+							Description: "Group is the IP of the multicast group.",
+							Type:        []string{"string"},
+							Format:      "",
+						},
+					},
+					"pods": {
+						SchemaProps: spec.SchemaProps{
+							Description: "Pods is the list of Pods that have joined the multicast group.",
+							Type:        []string{"array"},
+							Items: &spec.SchemaOrArray{
+								Schema: &spec.Schema{
+									SchemaProps: spec.SchemaProps{
+										Default: map[string]interface{}{},
+										Ref:     ref("antrea.io/antrea/pkg/apis/stats/v1alpha1.PodReference"),
+									},
+								},
+							},
+						},
+					},
+				},
+				Required: []string{"pods"},
+			},
+		},
+		Dependencies: []string{
+			"antrea.io/antrea/pkg/apis/stats/v1alpha1.PodReference", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
+	}
+}
+
+func schema_pkg_apis_stats_v1alpha1_MulticastGroupList(ref common.ReferenceCallback) common.OpenAPIDefinition {
+	return common.OpenAPIDefinition{
+		Schema: spec.Schema{
+			SchemaProps: spec.SchemaProps{
+				Description: "MulticastGroupList is a list of MulticastGroup.",
+				Type:        []string{"object"},
+				Properties: map[string]spec.Schema{
+					"kind": {
+						SchemaProps: spec.SchemaProps{
+							Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+							Type:        []string{"string"},
+							Format:      "",
+						},
+					},
+					"apiVersion": {
+						SchemaProps: spec.SchemaProps{
+							Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+							Type:        []string{"string"},
+							Format:      "",
+						},
+					},
+					"metadata": {
+						SchemaProps: spec.SchemaProps{
+							Default: map[string]interface{}{},
+							Ref:     ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
+						},
+					},
+					"items": {
+						SchemaProps: spec.SchemaProps{
+							Description: "List of MulticastGroup.",
+							Type:        []string{"array"},
+							Items: &spec.SchemaOrArray{
+								Schema: &spec.Schema{
+									SchemaProps: spec.SchemaProps{
+										Default: map[string]interface{}{},
+										Ref:     ref("antrea.io/antrea/pkg/apis/stats/v1alpha1.MulticastGroup"),
+									},
+								},
+							},
+						},
+					},
+				},
+				Required: []string{"items"},
+			},
+		},
+		Dependencies: []string{
+			"antrea.io/antrea/pkg/apis/stats/v1alpha1.MulticastGroup", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
+	}
+}
+
 func schema_pkg_apis_stats_v1alpha1_NetworkPolicyStats(ref common.ReferenceCallback) common.OpenAPIDefinition {
 	return common.OpenAPIDefinition{
 		Schema: spec.Schema{
@@ -2638,6 +2799,33 @@ func schema_pkg_apis_stats_v1alpha1_NetworkPolicyStatsList(ref common.ReferenceC
 	}
 }
 
+func schema_pkg_apis_stats_v1alpha1_PodReference(ref common.ReferenceCallback) common.OpenAPIDefinition {
+	return common.OpenAPIDefinition{
+		Schema: spec.Schema{
+			SchemaProps: spec.SchemaProps{
+				Description: "PodReference represents a Pod Reference.",
+				Type:        []string{"object"},
+				Properties: map[string]spec.Schema{
+					"name": {
+						SchemaProps: spec.SchemaProps{
+							Description: "The name of this Pod.",
+							Type:        []string{"string"},
+							Format:      "",
+						},
+					},
+					"namespace": {
+						SchemaProps: spec.SchemaProps{
+							Description: "The namespace of this Pod.",
+							Type:        []string{"string"},
+							Format:      "",
+						},
+					},
+				},
+			},
+		},
+	}
+}
+
 func schema_pkg_apis_stats_v1alpha1_RuleTrafficStats(ref common.ReferenceCallback) common.OpenAPIDefinition {
 	return common.OpenAPIDefinition{
 		Schema: spec.Schema{
diff --git a/pkg/client/clientset/versioned/typed/stats/v1alpha1/fake/fake_multicastgroup.go b/pkg/client/clientset/versioned/typed/stats/v1alpha1/fake/fake_multicastgroup.go
new file mode 100644
index 000000000..81c8cfecf
--- /dev/null
+++ b/pkg/client/clientset/versioned/typed/stats/v1alpha1/fake/fake_multicastgroup.go
@@ -0,0 +1,74 @@
+// Copyright 2022 Antrea Authors
+//
+// 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.
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+	"context"
+
+	v1alpha1 "antrea.io/antrea/pkg/apis/stats/v1alpha1"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	labels "k8s.io/apimachinery/pkg/labels"
+	schema "k8s.io/apimachinery/pkg/runtime/schema"
+	watch "k8s.io/apimachinery/pkg/watch"
+	testing "k8s.io/client-go/testing"
+)
+
+// FakeMulticastGroups implements MulticastGroupInterface
+type FakeMulticastGroups struct {
+	Fake *FakeStatsV1alpha1
+}
+
+var multicastgroupsResource = schema.GroupVersionResource{Group: "stats.antrea.io", Version: "v1alpha1", Resource: "multicastgroups"}
+
+var multicastgroupsKind = schema.GroupVersionKind{Group: "stats.antrea.io", Version: "v1alpha1", Kind: "MulticastGroup"}
+
+// Get takes name of the multicastGroup, and returns the corresponding multicastGroup object, and an error if there is any.
+func (c *FakeMulticastGroups) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.MulticastGroup, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewRootGetAction(multicastgroupsResource, name), &v1alpha1.MulticastGroup{})
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1alpha1.MulticastGroup), err
+}
+
+// List takes label and field selectors, and returns the list of MulticastGroups that match those selectors.
+func (c *FakeMulticastGroups) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.MulticastGroupList, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewRootListAction(multicastgroupsResource, multicastgroupsKind, opts), &v1alpha1.MulticastGroupList{})
+	if obj == nil {
+		return nil, err
+	}
+
+	label, _, _ := testing.ExtractFromListOptions(opts)
+	if label == nil {
+		label = labels.Everything()
+	}
+	list := &v1alpha1.MulticastGroupList{ListMeta: obj.(*v1alpha1.MulticastGroupList).ListMeta}
+	for _, item := range obj.(*v1alpha1.MulticastGroupList).Items {
+		if label.Matches(labels.Set(item.Labels)) {
+			list.Items = append(list.Items, item)
+		}
+	}
+	return list, err
+}
+
+// Watch returns a watch.Interface that watches the requested multicastGroups.
+func (c *FakeMulticastGroups) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+	return c.Fake.
+		InvokesWatch(testing.NewRootWatchAction(multicastgroupsResource, opts))
+}
diff --git a/pkg/client/clientset/versioned/typed/stats/v1alpha1/fake/fake_stats_client.go b/pkg/client/clientset/versioned/typed/stats/v1alpha1/fake/fake_stats_client.go
index 07158ff9e..1d4a10166 100644
--- a/pkg/client/clientset/versioned/typed/stats/v1alpha1/fake/fake_stats_client.go
+++ b/pkg/client/clientset/versioned/typed/stats/v1alpha1/fake/fake_stats_client.go
@@ -1,4 +1,4 @@
-// Copyright 2021 Antrea Authors
+// Copyright 2022 Antrea Authors
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -34,6 +34,10 @@ func (c *FakeStatsV1alpha1) AntreaNetworkPolicyStats(namespace string) v1alpha1.
 	return &FakeAntreaNetworkPolicyStats{c, namespace}
 }
 
+func (c *FakeStatsV1alpha1) MulticastGroups() v1alpha1.MulticastGroupInterface {
+	return &FakeMulticastGroups{c}
+}
+
 func (c *FakeStatsV1alpha1) NetworkPolicyStats(namespace string) v1alpha1.NetworkPolicyStatsInterface {
 	return &FakeNetworkPolicyStats{c, namespace}
 }
diff --git a/pkg/client/clientset/versioned/typed/stats/v1alpha1/generated_expansion.go b/pkg/client/clientset/versioned/typed/stats/v1alpha1/generated_expansion.go
index 293e0ee75..152ec4a23 100644
--- a/pkg/client/clientset/versioned/typed/stats/v1alpha1/generated_expansion.go
+++ b/pkg/client/clientset/versioned/typed/stats/v1alpha1/generated_expansion.go
@@ -1,4 +1,4 @@
-// Copyright 2021 Antrea Authors
+// Copyright 2022 Antrea Authors
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -20,4 +20,6 @@ type AntreaClusterNetworkPolicyStatsExpansion interface{}
 
 type AntreaNetworkPolicyStatsExpansion interface{}
 
+type MulticastGroupExpansion interface{}
+
 type NetworkPolicyStatsExpansion interface{}
diff --git a/pkg/client/clientset/versioned/typed/stats/v1alpha1/multicastgroup.go b/pkg/client/clientset/versioned/typed/stats/v1alpha1/multicastgroup.go
new file mode 100644
index 000000000..ee3b92db1
--- /dev/null
+++ b/pkg/client/clientset/versioned/typed/stats/v1alpha1/multicastgroup.go
@@ -0,0 +1,96 @@
+// Copyright 2022 Antrea Authors
+//
+// 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.
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+	"context"
+	"time"
+
+	v1alpha1 "antrea.io/antrea/pkg/apis/stats/v1alpha1"
+	scheme "antrea.io/antrea/pkg/client/clientset/versioned/scheme"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	watch "k8s.io/apimachinery/pkg/watch"
+	rest "k8s.io/client-go/rest"
+)
+
+// MulticastGroupsGetter has a method to return a MulticastGroupInterface.
+// A group's client should implement this interface.
+type MulticastGroupsGetter interface {
+	MulticastGroups() MulticastGroupInterface
+}
+
+// MulticastGroupInterface has methods to work with MulticastGroup resources.
+type MulticastGroupInterface interface {
+	Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.MulticastGroup, error)
+	List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.MulticastGroupList, error)
+	Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
+	MulticastGroupExpansion
+}
+
+// multicastGroups implements MulticastGroupInterface
+type multicastGroups struct {
+	client rest.Interface
+}
+
+// newMulticastGroups returns a MulticastGroups
+func newMulticastGroups(c *StatsV1alpha1Client) *multicastGroups {
+	return &multicastGroups{
+		client: c.RESTClient(),
+	}
+}
+
+// Get takes name of the multicastGroup, and returns the corresponding multicastGroup object, and an error if there is any.
+func (c *multicastGroups) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.MulticastGroup, err error) {
+	result = &v1alpha1.MulticastGroup{}
+	err = c.client.Get().
+		Resource("multicastgroups").
+		Name(name).
+		VersionedParams(&options, scheme.ParameterCodec).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// List takes label and field selectors, and returns the list of MulticastGroups that match those selectors.
+func (c *multicastGroups) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.MulticastGroupList, err error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	result = &v1alpha1.MulticastGroupList{}
+	err = c.client.Get().
+		Resource("multicastgroups").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Watch returns a watch.Interface that watches the requested multicastGroups.
+func (c *multicastGroups) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	opts.Watch = true
+	return c.client.Get().
+		Resource("multicastgroups").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Watch(ctx)
+}
diff --git a/pkg/client/clientset/versioned/typed/stats/v1alpha1/stats_client.go b/pkg/client/clientset/versioned/typed/stats/v1alpha1/stats_client.go
index 9ed58f6ca..88d009e10 100644
--- a/pkg/client/clientset/versioned/typed/stats/v1alpha1/stats_client.go
+++ b/pkg/client/clientset/versioned/typed/stats/v1alpha1/stats_client.go
@@ -28,6 +28,7 @@ type StatsV1alpha1Interface interface {
 	RESTClient() rest.Interface
 	AntreaClusterNetworkPolicyStatsGetter
 	AntreaNetworkPolicyStatsGetter
+	MulticastGroupsGetter
 	NetworkPolicyStatsGetter
 }
 
@@ -44,6 +45,10 @@ func (c *StatsV1alpha1Client) AntreaNetworkPolicyStats(namespace string) AntreaN
 	return newAntreaNetworkPolicyStats(c, namespace)
 }
 
+func (c *StatsV1alpha1Client) MulticastGroups() MulticastGroupInterface {
+	return newMulticastGroups(c)
+}
+
 func (c *StatsV1alpha1Client) NetworkPolicyStats(namespace string) NetworkPolicyStatsInterface {
 	return newNetworkPolicyStats(c, namespace)
 }


Test patch:
diff --git a/pkg/agent/openflow/testing/mock_openflow.go b/pkg/agent/openflow/testing/mock_openflow.go
index 8e47d69fc..38feb97b9 100644
--- a/pkg/agent/openflow/testing/mock_openflow.go
+++ b/pkg/agent/openflow/testing/mock_openflow.go
@@ -615,15 +615,15 @@ func (mr *MockClientMockRecorder) SendUDPPacketOut(arg0, arg1, arg2, arg3, arg4,
 }
 
 // StartPacketInHandler mocks base method
-func (m *MockClient) StartPacketInHandler(arg0 []byte, arg1 <-chan struct{}) {
+func (m *MockClient) StartPacketInHandler(arg0 <-chan struct{}) {
 	m.ctrl.T.Helper()
-	m.ctrl.Call(m, "StartPacketInHandler", arg0, arg1)
+	m.ctrl.Call(m, "StartPacketInHandler", arg0)
 }
 
 // StartPacketInHandler indicates an expected call of StartPacketInHandler
-func (mr *MockClientMockRecorder) StartPacketInHandler(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockClientMockRecorder) StartPacketInHandler(arg0 interface{}) *gomock.Call {
 	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartPacketInHandler", reflect.TypeOf((*MockClient)(nil).StartPacketInHandler), arg0, arg1)
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartPacketInHandler", reflect.TypeOf((*MockClient)(nil).StartPacketInHandler), arg0)
 }
 
 // SubscribePacketIn mocks base method
diff --git a/test/e2e/k8s_util.go b/test/e2e/k8s_util.go
index bcf581c7b..ab6cb5d1e 100644
--- a/test/e2e/k8s_util.go
+++ b/test/e2e/k8s_util.go
@@ -229,8 +229,17 @@ func DecidePingProbeResult(stdout string, probeNum int) PodConnectivityMark {
 	// --- 10.10.1.2 ping statistics ---
 	// 3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2042ms
 	// =======================================================
+	// =================== Rejected ICMPv6 stdout ===================
+	// PING fd02:0:0:f8::11(fd02:0:0:f8::11) 56 data bytes
+	// From fd02:0:0:f8::11 icmp_seq=1 Destination unreachable: Administratively prohibited
+	// From fd02:0:0:f8::11 icmp_seq=2 Destination unreachable: Administratively prohibited
+	// From fd02:0:0:f8::11 icmp_seq=3 Destination unreachable: Administratively prohibited
+	//
+	// --- fd02:0:0:f8::11 ping statistics ---
+	// 3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2047ms
+	// =======================================================
 	countConnected := strings.Count(stdout, "bytes from")
-	countRejected := strings.Count(stdout, "Prohibited")
+	countRejected := strings.Count(stdout, "Prohibited") + strings.Count(stdout, "prohibited")
 	countDropped := probeNum - strings.Count(stdout, "icmp_seq")
 
 	if countRejected == 0 && countConnected > 0 {