44 "errors"
55 "fmt"
66 "net"
7+ "strconv"
78 "strings"
89
910 "k8s.io/klog/v2"
@@ -15,6 +16,7 @@ import (
1516 libovsdbops "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops"
1617 libovsdbutil "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/util"
1718 "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/nbdb"
19+ addressset "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/ovn/address_set"
1820 "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/types"
1921 "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/util"
2022 utilerrors "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/util/errors"
@@ -237,3 +239,150 @@ func (oc *DefaultNetworkController) getUDNOpenPortDbIDs(podNamespacedName string
237239 libovsdbops .PolicyDirectionKey : string (aclDir ),
238240 })
239241}
242+
243+ const advertisedNetworkIsolationACLID = "advertised-network-isolation"
244+ const advertisedNetworkSubnetsAddressSet = "advertised-network-subnets"
245+ const advertisedNetworkSubnetsCtrl = "advertised-network-subnets-controller"
246+
247+ func GetAdvertisedNetworkSubnetsAddressSetDBIDs () * libovsdbops.DbObjectIDs {
248+ return libovsdbops .NewDbObjectIDs (libovsdbops .AddressSetAdvertisedNetwork , advertisedNetworkSubnetsCtrl , map [libovsdbops.ExternalIDKey ]string {
249+ libovsdbops .ObjectNameKey : advertisedNetworkSubnetsAddressSet ,
250+ })
251+ }
252+
253+ func GetAdvertisedNetworkSubnetsDropACLdbIDs () * libovsdbops.DbObjectIDs {
254+ return libovsdbops .NewDbObjectIDs (libovsdbops .ACLAdvertisedNetwork , advertisedNetworkIsolationACLID ,
255+ map [libovsdbops.ExternalIDKey ]string {
256+ libovsdbops .ObjectNameKey : advertisedNetworkSubnetsCtrl ,
257+ libovsdbops .NetworkKey : "" ,
258+ })
259+ }
260+
261+ func GetAdvertisedNetworkSubnetsPassACLdbIDs (networkName string , networkID int ) * libovsdbops.DbObjectIDs {
262+ return libovsdbops .NewDbObjectIDs (libovsdbops .ACLAdvertisedNetwork , advertisedNetworkIsolationACLID ,
263+ map [libovsdbops.ExternalIDKey ]string {
264+ libovsdbops .ObjectNameKey : networkName ,
265+ libovsdbops .NetworkKey : strconv .Itoa (networkID ),
266+ })
267+ }
268+
269+ func BuildAdvertisedNetworkSubnetsDropACL (advertisedNetworkSubnetsAddressSet addressset.AddressSet ) * nbdb.ACL {
270+ var dropMatches []string
271+ v4AddrSet , v6AddrSet := advertisedNetworkSubnetsAddressSet .GetASHashNames ()
272+ if v4AddrSet != "" {
273+ dropMatches = append (dropMatches , fmt .Sprintf ("(ip4.src == $%s && ip4.dst == $%s)" , v4AddrSet , v4AddrSet ))
274+ }
275+ if v6AddrSet != "" {
276+ dropMatches = append (dropMatches , fmt .Sprintf ("(ip6.src == $%s && ip6.dst == $%s)" , v6AddrSet , v6AddrSet ))
277+ }
278+
279+ dropACL := libovsdbutil .BuildACL (
280+ GetAdvertisedNetworkSubnetsDropACLdbIDs (),
281+ types .AdvertisedNetworkDenyPriority ,
282+ strings .Join (dropMatches , " || " ),
283+ nbdb .ACLActionDrop ,
284+ nil ,
285+ libovsdbutil .LportEgressAfterLB )
286+ dropACL .Tier = types .PrimaryACLTier
287+ return dropACL
288+ }
289+
290+ func (bnc * BaseNetworkController ) addAdvertisedNetworkIsolation (nodeName string ) error {
291+ var passMatches , cidrs []string
292+ var ops []ovsdb.Operation
293+
294+ addrSet , err := bnc .addressSetFactory .GetAddressSet (GetAdvertisedNetworkSubnetsAddressSetDBIDs ())
295+ if err != nil {
296+ return fmt .Errorf ("failed to get advertised subnets addresset %s for network %s: %w" , GetAdvertisedNetworkSubnetsAddressSetDBIDs (), bnc .GetNetworkName (), err )
297+ }
298+
299+ for _ , subnet := range bnc .Subnets () {
300+ ipPrefix := "ip4"
301+ if utilnet .IsIPv6CIDR (subnet .CIDR ) {
302+ ipPrefix = "ip6"
303+ }
304+ passMatches = append (passMatches , fmt .Sprintf ("(%s.src == %s && %s.dst == %s)" , ipPrefix , subnet .CIDR , ipPrefix , subnet .CIDR ))
305+ cidrs = append (cidrs , subnet .CIDR .String ())
306+
307+ }
308+
309+ addrOps , err := addrSet .AddAddressesReturnOps (cidrs )
310+ if err != nil {
311+ return fmt .Errorf ("failed to add addresses %q to the %s address set for network %s: %w" , cidrs , GetAdvertisedNetworkSubnetsAddressSetDBIDs (), bnc .GetNetworkName (), err )
312+ }
313+ ops = append (ops , addrOps ... )
314+
315+ if len (passMatches ) > 0 {
316+ passACL := libovsdbutil .BuildACL (
317+ GetAdvertisedNetworkSubnetsPassACLdbIDs (bnc .GetNetworkName (), bnc .GetNetworkID ()),
318+ types .AdvertisedNetworkPassPriority ,
319+ strings .Join (passMatches , " || " ),
320+ nbdb .ACLActionPass ,
321+ nil ,
322+ libovsdbutil .LportEgressAfterLB )
323+ passACL .Tier = types .PrimaryACLTier
324+
325+ ops , err = libovsdbops .CreateOrUpdateACLsOps (bnc .nbClient , ops , nil , passACL )
326+ if err != nil {
327+ return fmt .Errorf ("failed to create or update network isolation pass ACL %s for network %s: %w" , GetAdvertisedNetworkSubnetsPassACLdbIDs (bnc .GetNetworkName (), bnc .GetNetworkID ()), bnc .GetNetworkName (), err )
328+ }
329+ ops , err = libovsdbops .AddACLsToLogicalSwitchOps (bnc .nbClient , ops , bnc .GetNetworkScopedSwitchName (nodeName ), passACL )
330+ if err != nil {
331+ return fmt .Errorf ("failed to add network isolation pass ACL to switch %s for network %s: %w" , bnc .GetNetworkScopedSwitchName (nodeName ), bnc .GetNetworkName (), err )
332+ }
333+ }
334+
335+ dropACL := BuildAdvertisedNetworkSubnetsDropACL (addrSet )
336+ ops , err = libovsdbops .CreateOrUpdateACLsOps (bnc .nbClient , ops , nil , dropACL )
337+ if err != nil {
338+ return fmt .Errorf ("failed to create or update network isolation drop ACL %v" , err )
339+ }
340+ ops , err = libovsdbops .AddACLsToLogicalSwitchOps (bnc .nbClient , ops , bnc .GetNetworkScopedSwitchName (nodeName ), dropACL )
341+ if err != nil {
342+ return fmt .Errorf ("failed to add network isolation drop ACL to switch %s for network %s: %w" , bnc .GetNetworkScopedSwitchName (nodeName ), bnc .GetNetworkName (), err )
343+ }
344+
345+ if _ , err = libovsdbops .TransactAndCheck (bnc .nbClient , ops ); err != nil {
346+ return fmt .Errorf ("failed to configure network isolation OVN rules for network %s: %w" , bnc .GetNetworkName (), err )
347+ }
348+ return nil
349+ }
350+
351+ func (bnc * BaseNetworkController ) deleteAdvertisedNetworkIsolation (nodeName string ) error {
352+ addrSet , err := bnc .addressSetFactory .GetAddressSet (GetAdvertisedNetworkSubnetsAddressSetDBIDs ())
353+ if err != nil {
354+ return fmt .Errorf ("failed to get advertised subnets addresset %s for network %s: %w" , GetAdvertisedNetworkSubnetsAddressSetDBIDs (), bnc .GetNetworkName (), err )
355+ }
356+
357+ var cidrs []string
358+ for _ , subnet := range bnc .Subnets () {
359+ cidrs = append (cidrs , subnet .CIDR .String ())
360+ }
361+ err = addrSet .DeleteAddresses (cidrs )
362+ if err != nil {
363+ return err
364+ }
365+
366+ passACLIDs := GetAdvertisedNetworkSubnetsPassACLdbIDs (bnc .GetNetworkName (), bnc .GetNetworkID ())
367+ passACLPredicate := libovsdbops .GetPredicate [* nbdb.ACL ](passACLIDs , nil )
368+ passACLs , err := libovsdbops .FindACLsWithPredicate (bnc .nbClient , passACLPredicate )
369+ if err != nil {
370+ return fmt .Errorf ("unable to find the pass ACL for advertised network %s: %w" , bnc .GetNetworkName (), err )
371+ }
372+
373+ dropACLIDs := GetAdvertisedNetworkSubnetsDropACLdbIDs ()
374+ dropACLPredicate := libovsdbops .GetPredicate [* nbdb.ACL ](dropACLIDs , nil )
375+ dropACLs , err := libovsdbops .FindACLsWithPredicate (bnc .nbClient , dropACLPredicate )
376+ if err != nil {
377+ return fmt .Errorf ("unable to find the drop ACL for advertised network %s: %w" , bnc .GetNetworkName (), err )
378+ }
379+
380+ // ACLs referenced by the switch will be deleted by db if there are no other references
381+ p := func (sw * nbdb.LogicalSwitch ) bool { return sw .Name == bnc .GetNetworkScopedSwitchName (nodeName ) }
382+ err = libovsdbops .RemoveACLsFromLogicalSwitchesWithPredicate (bnc .nbClient , p , append (passACLs , dropACLs ... )... )
383+ if err != nil {
384+ return fmt .Errorf ("failed to remove network isolation ACLs from the %s switch for network %s: %w" , bnc .GetNetworkScopedSwitchName (nodeName ), bnc .GetNetworkName (), err )
385+ }
386+
387+ return nil
388+ }
0 commit comments