Skip to content

Commit b3f38b8

Browse files
committed
Add an annotation for enabling multicast on a namespace
1 parent 5cd6d38 commit b3f38b8

8 files changed

+97
-42
lines changed

pkg/sdn/api/plugin.go

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ const (
1717
// HostSubnet annotations. (Note: should be "hostsubnet.network.openshift.io/", but the incorrect name is now part of the API.)
1818
AssignHostSubnetAnnotation = "pod.network.openshift.io/assign-subnet"
1919
FixedVNIDHostAnnotation = "pod.network.openshift.io/fixed-vnid-host"
20+
21+
// NetNamespace annotations
22+
MulticastEnabledAnnotation = "netnamespace.network.openshift.io/multicast-enabled"
2023
)
2124

2225
func IsOpenShiftNetworkPlugin(pluginName string) bool {

pkg/sdn/plugin/multitenant.go

+31-22
Original file line numberDiff line numberDiff line change
@@ -64,36 +64,38 @@ func (mp *multiTenantPlugin) updatePodNetwork(namespace string, oldNetID, netID
6464
services = &kapi.ServiceList{}
6565
}
6666

67-
movedVNIDRefs := 0
67+
if oldNetID != netID {
68+
movedVNIDRefs := 0
69+
70+
// Update OF rules for the existing/old pods in the namespace
71+
for _, pod := range pods {
72+
err = mp.node.UpdatePod(pod)
73+
if err == nil {
74+
movedVNIDRefs++
75+
} else {
76+
glog.Errorf("Could not update pod %q in namespace %q: %v", pod.Name, namespace, err)
77+
}
78+
}
79+
80+
// Update OF rules for the old services in the namespace
81+
for _, svc := range services.Items {
82+
if !kapi.IsServiceIPSet(&svc) {
83+
continue
84+
}
6885

69-
// Update OF rules for the existing/old pods in the namespace
70-
for _, pod := range pods {
71-
err = mp.node.UpdatePod(pod)
72-
if err == nil {
86+
mp.node.DeleteServiceRules(&svc)
87+
mp.node.AddServiceRules(&svc, netID)
7388
movedVNIDRefs++
74-
} else {
75-
glog.Errorf("Could not update pod %q in namespace %q: %v", pod.Name, namespace, err)
7689
}
77-
}
7890

79-
// Update OF rules for the old services in the namespace
80-
for _, svc := range services.Items {
81-
if !kapi.IsServiceIPSet(&svc) {
82-
continue
91+
if movedVNIDRefs > 0 {
92+
mp.moveVNIDRefs(movedVNIDRefs, oldNetID, netID)
8393
}
8494

85-
mp.node.DeleteServiceRules(&svc)
86-
mp.node.AddServiceRules(&svc, netID)
87-
movedVNIDRefs++
88-
}
89-
90-
if movedVNIDRefs > 0 {
91-
mp.moveVNIDRefs(movedVNIDRefs, oldNetID, netID)
95+
// Update namespace references in egress firewall rules
96+
mp.node.UpdateEgressNetworkPolicyVNID(namespace, oldNetID, netID)
9297
}
9398

94-
// Update namespace references in egress firewall rules
95-
mp.node.UpdateEgressNetworkPolicyVNID(namespace, oldNetID, netID)
96-
9799
// Update local multicast rules
98100
mp.node.podManager.UpdateLocalMulticastRules(oldNetID)
99101
mp.node.podManager.UpdateLocalMulticastRules(netID)
@@ -119,6 +121,13 @@ func (mp *multiTenantPlugin) GetNamespaces(vnid uint32) []string {
119121
return mp.vnids.GetNamespaces(vnid)
120122
}
121123

124+
func (mp *multiTenantPlugin) GetMCEnabled(vnid uint32) bool {
125+
if vnid == osapi.GlobalVNID {
126+
return false
127+
}
128+
return mp.vnids.GetMCEnabled(vnid)
129+
}
130+
122131
func (mp *multiTenantPlugin) RefVNID(vnid uint32) {
123132
if vnid == 0 {
124133
return

pkg/sdn/plugin/networkpolicy.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,11 @@ func (np *networkPolicyPlugin) AddNetNamespace(netns *osapi.NetNamespace) {
160160
}
161161

162162
func (np *networkPolicyPlugin) UpdateNetNamespace(netns *osapi.NetNamespace, oldNetID uint32) {
163-
glog.Warning("Got UpdateNetNamespace for namespace %s (%d) while using %s plugin", netns.NetName, netns.NetID, osapi.NetworkPolicyPluginName)
163+
if netns.NetID != oldNetID {
164+
glog.Warning("Got VNID change for namespace %s while using %s plugin", netns.NetName, osapi.NetworkPolicyPluginName)
165+
}
166+
167+
np.node.podManager.UpdateLocalMulticastRules(netns.NetID)
164168
}
165169

166170
func (np *networkPolicyPlugin) DeleteNetNamespace(netns *osapi.NetNamespace) {
@@ -178,6 +182,10 @@ func (np *networkPolicyPlugin) GetNamespaces(vnid uint32) []string {
178182
return np.vnids.GetNamespaces(vnid)
179183
}
180184

185+
func (np *networkPolicyPlugin) GetMCEnabled(vnid uint32) bool {
186+
return np.vnids.GetMCEnabled(vnid)
187+
}
188+
181189
func (np *networkPolicyPlugin) syncNamespace(npns *npNamespace) {
182190
inUse := npns.refs > 0
183191
if !inUse && !npns.inUse {

pkg/sdn/plugin/node.go

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ type osdnPolicy interface {
4040

4141
GetVNID(namespace string) (uint32, error)
4242
GetNamespaces(vnid uint32) []string
43+
GetMCEnabled(vnid uint32) bool
4344

4445
RefVNID(vnid uint32)
4546
UnrefVNID(vnid uint32)

pkg/sdn/plugin/pod.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,10 @@ func localMulticastOutputs(runningPods map[string]*runningPod, vnid uint32) stri
205205
}
206206

207207
func (m *podManager) updateLocalMulticastRulesWithLock(vnid uint32) {
208-
outputs := localMulticastOutputs(m.runningPods, vnid)
208+
var outputs string
209+
if m.policy.GetMCEnabled(vnid) {
210+
outputs = localMulticastOutputs(m.runningPods, vnid)
211+
}
209212
otx := m.ovs.NewTransaction()
210213
if len(outputs) > 0 {
211214
otx.AddFlow("table=120, priority=100, reg0=%d, actions=%s", vnid, outputs)

pkg/sdn/plugin/singletenant.go

+4
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ func (sp *singleTenantPlugin) GetNamespaces(vnid uint32) []string {
3737
return nil
3838
}
3939

40+
func (sp *singleTenantPlugin) GetMCEnabled(vnid uint32) bool {
41+
return false
42+
}
43+
4044
func (sp *singleTenantPlugin) RefVNID(vnid uint32) {
4145
}
4246

pkg/sdn/plugin/vnids_node.go

+33-6
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ type nodeVNIDMap struct {
2323
// Synchronizes add or remove ids/namespaces
2424
lock sync.Mutex
2525
ids map[string]uint32
26+
mcEnabled map[string]bool
2627
namespaces map[uint32]sets.String
2728
}
2829

@@ -31,6 +32,7 @@ func newNodeVNIDMap(policy osdnPolicy, osClient *osclient.Client) *nodeVNIDMap {
3132
policy: policy,
3233
osClient: osClient,
3334
ids: make(map[string]uint32),
35+
mcEnabled: make(map[string]bool),
3436
namespaces: make(map[uint32]sets.String),
3537
}
3638
}
@@ -74,6 +76,22 @@ func (vmap *nodeVNIDMap) GetVNID(name string) (uint32, error) {
7476
return 0, fmt.Errorf("Failed to find netid for namespace: %s in vnid map", name)
7577
}
7678

79+
func (vmap *nodeVNIDMap) GetMCEnabled(id uint32) bool {
80+
vmap.lock.Lock()
81+
defer vmap.lock.Unlock()
82+
83+
set, exists := vmap.namespaces[id]
84+
if !exists || set.Len() == 0 {
85+
return false
86+
}
87+
for _, ns := range set.List() {
88+
if !vmap.mcEnabled[ns] {
89+
return false
90+
}
91+
}
92+
return true
93+
}
94+
7795
// Nodes asynchronously watch for both NetNamespaces and services
7896
// NetNamespaces populates vnid map and services/pod-setup depend on vnid map
7997
// If for some reason, vnid map propagation from master to node is slow
@@ -99,17 +117,18 @@ func (vmap *nodeVNIDMap) WaitAndGetVNID(name string) (uint32, error) {
99117
}
100118
}
101119

102-
func (vmap *nodeVNIDMap) setVNID(name string, id uint32) {
120+
func (vmap *nodeVNIDMap) setVNID(name string, id uint32, mcEnabled bool) {
103121
vmap.lock.Lock()
104122
defer vmap.lock.Unlock()
105123

106124
if oldId, found := vmap.ids[name]; found {
107125
vmap.removeNamespaceFromSet(name, oldId)
108126
}
109127
vmap.ids[name] = id
128+
vmap.mcEnabled[name] = mcEnabled
110129
vmap.addNamespaceToSet(name, id)
111130

112-
log.Infof("Associate netid %d to namespace %q", id, name)
131+
log.Infof("Associate netid %d to namespace %q with mcEnabled %v", id, name, mcEnabled)
113132
}
114133

115134
func (vmap *nodeVNIDMap) unsetVNID(name string) (id uint32, err error) {
@@ -122,18 +141,24 @@ func (vmap *nodeVNIDMap) unsetVNID(name string) (id uint32, err error) {
122141
}
123142
vmap.removeNamespaceFromSet(name, id)
124143
delete(vmap.ids, name)
144+
delete(vmap.mcEnabled, name)
125145
log.Infof("Dissociate netid %d from namespace %q", id, name)
126146
return id, nil
127147
}
128148

149+
func netnsIsMulticastEnabled(netns *osapi.NetNamespace) bool {
150+
enabled, ok := netns.Annotations[osapi.MulticastEnabledAnnotation]
151+
return enabled == "true" && ok
152+
}
153+
129154
func (vmap *nodeVNIDMap) populateVNIDs() error {
130155
nets, err := vmap.osClient.NetNamespaces().List(kapi.ListOptions{})
131156
if err != nil {
132157
return err
133158
}
134159

135160
for _, net := range nets.Items {
136-
vmap.setVNID(net.Name, net.NetID)
161+
vmap.setVNID(net.Name, net.NetID, netnsIsMulticastEnabled(&net))
137162
}
138163
return nil
139164
}
@@ -156,12 +181,14 @@ func (vmap *nodeVNIDMap) watchNetNamespaces() {
156181
log.V(5).Infof("Watch %s event for NetNamespace %q", delta.Type, netns.ObjectMeta.Name)
157182
switch delta.Type {
158183
case cache.Sync, cache.Added, cache.Updated:
159-
// Skip this event if the old and new network ids are same
184+
// Skip this event if nothing has changed
160185
oldNetID, err := vmap.GetVNID(netns.NetName)
161-
if (err == nil) && (oldNetID == netns.NetID) {
186+
oldMCEnabled := vmap.mcEnabled[netns.NetName]
187+
mcEnabled := netnsIsMulticastEnabled(netns)
188+
if err == nil && oldNetID == netns.NetID && oldMCEnabled == mcEnabled {
162189
break
163190
}
164-
vmap.setVNID(netns.NetName, netns.NetID)
191+
vmap.setVNID(netns.NetName, netns.NetID, mcEnabled)
165192

166193
if delta.Type == cache.Added {
167194
vmap.policy.AddNetNamespace(netns)

pkg/sdn/plugin/vnids_node_test.go

+12-12
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ func TestNodeVNIDMap(t *testing.T) {
1919

2020
// set vnids, non-overlapping
2121

22-
vmap.setVNID("alpha", 1)
23-
vmap.setVNID("bravo", 2)
24-
vmap.setVNID("charlie", 3)
25-
vmap.setVNID("delta", 4)
22+
vmap.setVNID("alpha", 1, false)
23+
vmap.setVNID("bravo", 2, false)
24+
vmap.setVNID("charlie", 3, false)
25+
vmap.setVNID("delta", 4, false)
2626

2727
checkExists(t, vmap, "alpha", 1)
2828
checkExists(t, vmap, "bravo", 2)
@@ -71,8 +71,8 @@ func TestNodeVNIDMap(t *testing.T) {
7171

7272
// change vnids
7373

74-
vmap.setVNID("bravo", 1)
75-
vmap.setVNID("delta", 2)
74+
vmap.setVNID("bravo", 1, false)
75+
vmap.setVNID("delta", 2, false)
7676

7777
checkExists(t, vmap, "bravo", 1)
7878
checkExists(t, vmap, "delta", 2)
@@ -86,12 +86,12 @@ func TestNodeVNIDMap(t *testing.T) {
8686

8787
// overlapping vnids
8888

89-
vmap.setVNID("echo", 3)
90-
vmap.setVNID("foxtrot", 5)
91-
vmap.setVNID("golf", 1)
92-
vmap.setVNID("hotel", 1)
93-
vmap.setVNID("india", 1)
94-
vmap.setVNID("juliet", 3)
89+
vmap.setVNID("echo", 3, false)
90+
vmap.setVNID("foxtrot", 5, false)
91+
vmap.setVNID("golf", 1, false)
92+
vmap.setVNID("hotel", 1, false)
93+
vmap.setVNID("india", 1, false)
94+
vmap.setVNID("juliet", 3, false)
9595

9696
checkExists(t, vmap, "bravo", 1)
9797
checkExists(t, vmap, "delta", 2)

0 commit comments

Comments
 (0)