Skip to content

Commit

Permalink
ctmap: add NAT purge for nodeport-backed DSR NAT entries
Browse files Browse the repository at this point in the history
With #22978 we changed how DSR NAT
entries are managed. Instead of associating the NAT entry's lifetime with
bpf_lxc's CT_INGRESS entry, the nodeport code on the backend now creates
its own CT_EGRESS entry. When such a CT_EGRESS entry is GC'ed, we should
therefore also purge the related DSR NAT entry.

Also add a test for this case.

Signed-off-by: Julian Wiedmann <jwi@isovalent.com>
  • Loading branch information
julianwiedmann authored and dylandreimerink committed Oct 30, 2023
1 parent c1a2d1f commit 21072cd
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 2 deletions.
12 changes: 10 additions & 2 deletions pkg/maps/ctmap/ctmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,9 +290,13 @@ func purgeCtEntry6(m *Map, key CtKey, entry *CtEntry, natMap *nat.Map) error {

if t.GetFlags()&tuple.TUPLE_F_IN != 0 {
if entry.isDsrEntry() {
// To delete NAT entries created by DSR
// To delete NAT entries created by legacy DSR
nat.DeleteSwappedMapping6(natMap, t.(*tuple.TupleKey6Global))
}
} else if t.GetFlags()&tuple.TUPLE_F_OUT == tuple.TUPLE_F_OUT &&
entry.isDsrEntry() {
// To delete NAT entries created by DSR
nat.DeleteSwappedMapping6(natMap, t.(*tuple.TupleKey6Global))
} else {
nat.DeleteMapping6(natMap, t.(*tuple.TupleKey6Global))
}
Expand Down Expand Up @@ -401,9 +405,13 @@ func purgeCtEntry4(m *Map, key CtKey, entry *CtEntry, natMap *nat.Map) error {

if t.GetFlags()&tuple.TUPLE_F_IN != 0 {
if entry.isDsrEntry() {
// To delete NAT entries created by DSR
// To delete NAT entries created by legacy DSR
nat.DeleteSwappedMapping4(natMap, t.(*tuple.TupleKey4Global))
}
} else if t.GetFlags()&tuple.TUPLE_F_OUT == tuple.TUPLE_F_OUT &&
entry.isDsrEntry() {
// To delete NAT entries created by DSR
nat.DeleteSwappedMapping4(natMap, t.(*tuple.TupleKey4Global))
} else {
nat.DeleteMapping4(natMap, t.(*tuple.TupleKey4Global))
}
Expand Down
89 changes: 89 additions & 0 deletions pkg/maps/ctmap/ctmap_privileged_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,95 @@ func (k *CTMapPrivilegedTestSuite) TestCtGcTcp(c *C) {
c.Assert(len(buf), Equals, 0)
}

// TestCtGcDsr tests whether DSR NAT entries are removed upon a removal of
// their CT entry (== CT_EGRESS).
func (k *CTMapPrivilegedTestSuite) TestCtGcDsr(c *C) {
// Init maps
natMap := nat.NewMap("cilium_nat_any4_test", nat.IPv4, 1000)
err := natMap.OpenOrCreate()
c.Assert(err, IsNil)
defer natMap.Map.Unpin()

ctMapName := MapNameTCP4Global + "_test"
mapInfo[mapTypeIPv4TCPGlobal] = mapAttributes{
natMap: natMap, natMapLock: mapInfo[mapTypeIPv4TCPGlobal].natMapLock,
}

ctMap := newMap(ctMapName, mapTypeIPv4TCPGlobal)
err = ctMap.OpenOrCreate()
c.Assert(err, IsNil)
defer ctMap.Map.Unpin()

// Create the following entries and check that they get GC-ed:
// - CT: TCP OUT 1.1.1.1:1111 -> 192.168.61.11:8080 <..>
// - NAT: TCP OUT 192.168.61.11:8080 -> 1.1.1.1:1111 XLATE_SRC 2.2.2.2:80

ctKey := &CtKey4Global{
tuple.TupleKey4Global{
TupleKey4: tuple.TupleKey4{
SourceAddr: types.IPv4{192, 168, 61, 11},
DestAddr: types.IPv4{1, 1, 1, 1},
SourcePort: 0x5704,
DestPort: 0x901f,
NextHeader: u8proto.TCP,
Flags: tuple.TUPLE_F_OUT,
},
},
}
ctVal := &CtEntry{
TxPackets: 1,
TxBytes: 216,
Lifetime: 37459,
Flags: DSR,
}
err = ctMap.Map.Update(ctKey, ctVal)
c.Assert(err, IsNil)

natKey := &nat.NatKey4{
TupleKey4Global: tuple.TupleKey4Global{
TupleKey4: tuple.TupleKey4{
DestAddr: types.IPv4{1, 1, 1, 1},
SourceAddr: types.IPv4{192, 168, 61, 11},
DestPort: 0x5704,
SourcePort: 0x901f,
NextHeader: u8proto.TCP,
Flags: tuple.TUPLE_F_OUT,
},
},
}
natVal := &nat.NatEntry4{
Created: 37400,
Addr: types.IPv4{2, 2, 2, 2},
Port: 0x50,
}
err = natMap.Map.Update(natKey, natVal)
c.Assert(err, IsNil)

buf := make(map[string][]string)
err = ctMap.Map.Dump(buf)
c.Assert(err, IsNil)
c.Assert(len(buf), Equals, 1)

buf = make(map[string][]string)
err = natMap.Map.Dump(buf)
c.Assert(err, IsNil)
c.Assert(len(buf), Equals, 1)

// GC and check whether NAT entry has been collected
filter := &GCFilter{
RemoveExpired: true,
Time: 39000,
}
stats := doGC4(ctMap, filter)
c.Assert(stats.aliveEntries, Equals, uint32(0))
c.Assert(stats.deleted, Equals, uint32(1))

buf = make(map[string][]string)
err = natMap.Map.Dump(buf)
c.Assert(err, IsNil)
c.Assert(len(buf), Equals, 0)
}

// TestCtGcLegacyDsr tests whether DSR NAT entries are removed upon a removal of
// their legacy CT entry (== CT_INGRESS).
// See https://github.com/cilium/cilium/pull/22978 for details.
Expand Down

0 comments on commit 21072cd

Please sign in to comment.