mirror of
https://github.com/cloudnativelabs/kube-router.git
synced 2025-11-20 04:21:32 +01:00
Improve ipset performance with large sets
This commit updates kube-router to use `ipset restore` instead of calling `ipset add` multiple times in a row. This significantly improves its performance when working with large sets of rules. Ref: https://github.com/cloudnativelabs/kube-router/issues/962
This commit is contained in:
parent
e35dc9d61e
commit
a79ededd3c
@ -208,18 +208,20 @@ func (ipset *IPSet) Add(set *Set) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, entry := range set.Entries {
|
options := make([][]string, len(set.Entries))
|
||||||
_, err := ipset.Get(set.Name).Add(entry.Options...)
|
for index, entry := range set.Entries {
|
||||||
if err != nil {
|
options[index] = entry.Options
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ipset.Get(set.Name).BatchAdd(options)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a given entry to the set. If the -exist option is specified, ipset
|
// Add a given entry to the set. If the -exist option is specified, ipset
|
||||||
// ignores if the entry already added to the set.
|
// ignores if the entry already added to the set.
|
||||||
|
// Note: if you need to add multiple entries (e.g., in a loop), use BatchAdd instead,
|
||||||
|
// as it’s much more performant.
|
||||||
func (set *Set) Add(addOptions ...string) (*Entry, error) {
|
func (set *Set) Add(addOptions ...string) (*Entry, error) {
|
||||||
entry := &Entry{
|
entry := &Entry{
|
||||||
Set: set,
|
Set: set,
|
||||||
@ -233,6 +235,35 @@ func (set *Set) Add(addOptions ...string) (*Entry, error) {
|
|||||||
return entry, nil
|
return entry, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adds given entries (with their options) to the set.
|
||||||
|
// For multiple items, this is much faster than Add().
|
||||||
|
func (set *Set) BatchAdd(addOptions [][]string) error {
|
||||||
|
newEntries := make([]*Entry, len(addOptions))
|
||||||
|
for index, options := range addOptions {
|
||||||
|
entry := &Entry{
|
||||||
|
Set: set,
|
||||||
|
Options: options,
|
||||||
|
}
|
||||||
|
newEntries[index] = entry
|
||||||
|
}
|
||||||
|
set.Entries = append(set.Entries, newEntries...)
|
||||||
|
|
||||||
|
// Build the `restore` command contents
|
||||||
|
var builder strings.Builder
|
||||||
|
for _, options := range addOptions {
|
||||||
|
line := strings.Join(append([]string{"add", "-exist", set.name()}, options...), " ")
|
||||||
|
builder.WriteString(line + "\n")
|
||||||
|
}
|
||||||
|
restoreContents := builder.String()
|
||||||
|
|
||||||
|
// Invoke the command
|
||||||
|
_, err := set.Parent.runWithStdin(bytes.NewBufferString(restoreContents), "restore")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Del an entry from a set. If the -exist option is specified and the entry is
|
// Del an entry from a set. If the -exist option is specified and the entry is
|
||||||
// not in the set (maybe already expired), then the command is ignored.
|
// not in the set (maybe already expired), then the command is ignored.
|
||||||
func (entry *Entry) Del() error {
|
func (entry *Entry) Del() error {
|
||||||
@ -441,7 +472,19 @@ func (set *Set) Swap(setTo *Set) error {
|
|||||||
|
|
||||||
// Refresh a Set with new entries.
|
// Refresh a Set with new entries.
|
||||||
func (set *Set) Refresh(entries []string, extraOptions ...string) error {
|
func (set *Set) Refresh(entries []string, extraOptions ...string) error {
|
||||||
|
entriesWithOptions := make([][]string, len(entries))
|
||||||
|
|
||||||
|
for index, entry := range entries {
|
||||||
|
entriesWithOptions[index] = append([]string{entry}, extraOptions...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return set.RefreshWithBuiltinOptions(entriesWithOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refresh a Set with new entries with built-in options.
|
||||||
|
func (set *Set) RefreshWithBuiltinOptions(entries [][]string) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
// The set-name must be < 32 characters!
|
// The set-name must be < 32 characters!
|
||||||
tempName := set.Name + "-"
|
tempName := set.Name + "-"
|
||||||
|
|
||||||
@ -456,47 +499,10 @@ func (set *Set) Refresh(entries []string, extraOptions ...string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, entry := range entries {
|
err = newSet.BatchAdd(entries)
|
||||||
_, err = newSet.Add(entry)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
err = set.Swap(newSet)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = set.Parent.Destroy(tempName)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refresh a Set with new entries with built-in options.
|
|
||||||
func (set *Set) RefreshWithBuiltinOptions(entries [][]string) error {
|
|
||||||
var err error
|
|
||||||
tempName := set.Name + "-temp"
|
|
||||||
newSet := &Set{
|
|
||||||
Parent: set.Parent,
|
|
||||||
Name: tempName,
|
|
||||||
Options: set.Options,
|
|
||||||
}
|
|
||||||
|
|
||||||
err = set.Parent.Add(newSet)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, entry := range entries {
|
|
||||||
_, err = newSet.Add(entry...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = set.Swap(newSet)
|
err = set.Swap(newSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user