summaryrefslogtreecommitdiff
path: root/lib/mcast-snooping.h
blob: f120405da5707f223ecc780ace6051ea668dd6bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/*
 * Copyright (c) 2014 Red Hat, Inc.
 *
 * Based on mac-learning implementation.
 *
 * 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.
 */

#ifndef MCAST_SNOOPING_H
#define MCAST_SNOOPING_H 1

#include <time.h>
#include "dp-packet.h"
#include "openvswitch/hmap.h"
#include "openvswitch/list.h"
#include "ovs-atomic.h"
#include "ovs-thread.h"
#include "packets.h"
#include "timeval.h"

struct mcast_snooping;

/* Default maximum size of a mcast snooping table, in entries. */
#define MCAST_DEFAULT_MAX_ENTRIES 2048

/* Time, in seconds, before expiring a mcast_group due to inactivity. */
#define MCAST_ENTRY_DEFAULT_IDLE_TIME 300

/* Time, in seconds, before expiring a mrouter_port due to inactivity. */
#define MCAST_MROUTER_PORT_IDLE_TIME 180

/* Multicast group entry.
 * Guarded by owning 'mcast_snooping''s rwlock. */
struct mcast_group {
    /* Node in parent struct mcast_snooping hmap. */
    struct hmap_node hmap_node;

    /* Multicast group IPv6/IPv4 address. */
    struct in6_addr addr;

    /* VLAN tag. */
    uint16_t vlan;

    /* Node in parent struct mcast_snooping group_lru. */
    struct ovs_list group_node OVS_GUARDED;

    /* Contains struct mcast_group_bundle (ports), least recently used
     * at the front, most recently used at the back. */
    struct ovs_list bundle_lru OVS_GUARDED;
};

/* The bundle associated to the multicast group.
 * Guarded by owning 'mcast_snooping''s rwlock. */
struct mcast_group_bundle {
    /* Node in parent struct mcast_group bundle_lru list. */
    struct ovs_list bundle_node OVS_GUARDED;

    /* When this node expires. */
    time_t expires;

    /* Learned port. */
    void *port OVS_GUARDED;
};

/* The bundle connected to a multicast router.
 * Guarded by owning 'mcast_snooping''s rwlock. */
struct mcast_mrouter_bundle {
    /* Node in parent struct mcast_group mrouter_lru list. */
    struct ovs_list mrouter_node OVS_GUARDED;

    /* When this node expires. */
    time_t expires;

    /* VLAN tag. */
    uint16_t vlan;

    /* Learned port. */
    void *port OVS_GUARDED;
};

/* The bundle to send multicast traffic or Reports.
 * Guarded by owning 'mcast_snooping''s rwlock */
struct mcast_port_bundle {
    /* Node in parent struct mcast_snooping. */
    struct ovs_list node;

    /* VLAN tag. */
    uint16_t vlan;

    /* Learned port. */
    void *port;
};

/* Multicast snooping table. */
struct mcast_snooping {
    /* Snooping/learning table. */
    struct hmap table;

    /* Contains struct mcast_group, least recently used at the front,
     * most recently used at the back. */
    struct ovs_list group_lru OVS_GUARDED;

    /* Contains struct mcast_mrouter_bundle, least recently used at the
     * front, most recently used at the back. */
    struct ovs_list mrouter_lru OVS_GUARDED;

    /* Contains struct mcast_port_bundle to be flooded with multicast
     * packets in no special order. */
    struct ovs_list fport_list OVS_GUARDED;

    /* Contains struct mcast_port_bundle to forward Reports in
     * no special order. */
    struct ovs_list rport_list OVS_GUARDED;

    /* Secret for randomizing hash table. */
    uint32_t secret;

    /* Maximum age before deleting an entry. */
    unsigned int idle_time;

    /* Maximum number of multicast groups learned. */
    size_t max_entries;

    /* True if flow revalidation is needed. */
    bool need_revalidate;

    /* True if unregistered multicast packets should be flooded to all
     * ports, otherwise send them to ports connected to multicast routers. */
    bool flood_unreg;

    struct ovs_refcount ref_cnt;
    struct ovs_rwlock rwlock;
};

/* Basics. */
bool mcast_snooping_enabled(const struct mcast_snooping *ms);
bool mcast_snooping_flood_unreg(const struct mcast_snooping *ms);
int mcast_mrouter_age(const struct mcast_snooping *ms,
                      const struct mcast_mrouter_bundle *m);
int mcast_bundle_age(const struct mcast_snooping *ms,
                     const struct mcast_group_bundle *b);
struct mcast_snooping *mcast_snooping_create(void);
struct mcast_snooping *mcast_snooping_ref(const struct mcast_snooping *);
void mcast_snooping_unref(struct mcast_snooping *);
bool mcast_snooping_run(struct mcast_snooping *ms);
void mcast_snooping_wait(struct mcast_snooping *ms);

/* Configuration. */
void mcast_snooping_set_idle_time(struct mcast_snooping *ms,
                                  unsigned int idle_time)
    OVS_REQ_WRLOCK(ms->rwlock);
void mcast_snooping_set_max_entries(struct mcast_snooping *ms,
                                    size_t max_entries)
    OVS_REQ_WRLOCK(ms->rwlock);
bool
mcast_snooping_set_flood_unreg(struct mcast_snooping *ms, bool enable)
    OVS_REQ_WRLOCK(ms->rwlock);
void mcast_snooping_set_port_flood(struct mcast_snooping *ms, void *port,
                                   bool flood)
    OVS_REQ_WRLOCK(ms->rwlock);
void mcast_snooping_set_port_flood_reports(struct mcast_snooping *ms,
                                           void *port, bool flood)
    OVS_REQ_WRLOCK(ms->rwlock);

/* Lookup. */
struct mcast_group *
mcast_snooping_lookup(const struct mcast_snooping *ms,
                      const struct in6_addr *dip, uint16_t vlan)
    OVS_REQ_RDLOCK(ms->rwlock);
struct mcast_group *
mcast_snooping_lookup4(const struct mcast_snooping *ms, ovs_be32 ip4,
                       uint16_t vlan)
    OVS_REQ_RDLOCK(ms->rwlock);

/* Learning. */
bool mcast_snooping_add_group(struct mcast_snooping *ms,
                              const struct in6_addr *addr,
                              uint16_t vlan, void *port)
    OVS_REQ_WRLOCK(ms->rwlock);
bool mcast_snooping_add_group4(struct mcast_snooping *ms, ovs_be32 ip4,
                               uint16_t vlan, void *port)
    OVS_REQ_WRLOCK(ms->rwlock);
int mcast_snooping_add_report(struct mcast_snooping *ms,
                              const struct dp_packet *p,
                              uint16_t vlan, void *port)
    OVS_REQ_WRLOCK(ms->rwlock);
int mcast_snooping_add_mld(struct mcast_snooping *ms,
                           const struct dp_packet *p,
                           uint16_t vlan, void *port)
    OVS_REQ_WRLOCK(ms->rwlock);
bool mcast_snooping_leave_group(struct mcast_snooping *ms,
                                const struct in6_addr *addr,
                                uint16_t vlan, void *port)
    OVS_REQ_WRLOCK(ms->rwlock);
bool mcast_snooping_leave_group4(struct mcast_snooping *ms, ovs_be32 ip4,
                                 uint16_t vlan, void *port)
    OVS_REQ_WRLOCK(ms->rwlock);
bool mcast_snooping_add_mrouter(struct mcast_snooping *ms, uint16_t vlan,
                                void *port)
    OVS_REQ_WRLOCK(ms->rwlock);
bool mcast_snooping_is_query(ovs_be16 igmp_type);
bool mcast_snooping_is_membership(ovs_be16 igmp_type);

/* Flush. */
void mcast_snooping_mdb_flush(struct mcast_snooping *ms);
void mcast_snooping_flush(struct mcast_snooping *ms);
void mcast_snooping_flush_bundle(struct mcast_snooping *ms, void *port);

#endif /* mcast-snooping.h */