|
15 | 15 | package descriptor
|
16 | 16 |
|
17 | 17 | import (
|
| 18 | + "bytes" |
| 19 | + "fmt" |
18 | 20 | "strings"
|
19 | 21 |
|
20 | 22 | "github.com/golang/protobuf/proto"
|
21 | 23 | "github.com/pkg/errors"
|
22 | 24 | "go.ligato.io/cn-infra/v2/logging"
|
23 |
| - |
24 | 25 | kvs "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api"
|
25 | 26 | ifdescriptor "go.ligato.io/vpp-agent/v3/plugins/linux/ifplugin/descriptor"
|
26 | 27 | "go.ligato.io/vpp-agent/v3/plugins/linux/iptablesplugin/descriptor/adapter"
|
@@ -69,19 +70,22 @@ type RuleChainDescriptor struct {
|
69 | 70 |
|
70 | 71 | // parallelization of the Retrieve operation
|
71 | 72 | goRoutinesCnt int
|
| 73 | + // performance solution threshold |
| 74 | + minRuleCountForPerfRuleAddition int |
72 | 75 | }
|
73 | 76 |
|
74 | 77 | // NewRuleChainDescriptor creates a new instance of the iptables RuleChain descriptor.
|
75 | 78 | func NewRuleChainDescriptor(
|
76 | 79 | scheduler kvs.KVScheduler, ipTablesHandler linuxcalls.IPTablesAPI, nsPlugin nsplugin.API,
|
77 |
| - log logging.PluginLogger, goRoutinesCnt int) *kvs.KVDescriptor { |
| 80 | + log logging.PluginLogger, goRoutinesCnt int, minRuleCountForPerfRuleAddition int) *kvs.KVDescriptor { |
78 | 81 |
|
79 | 82 | descrCtx := &RuleChainDescriptor{
|
80 |
| - scheduler: scheduler, |
81 |
| - ipTablesHandler: ipTablesHandler, |
82 |
| - nsPlugin: nsPlugin, |
83 |
| - goRoutinesCnt: goRoutinesCnt, |
84 |
| - log: log.NewLogger("ipt-rulechain-descriptor"), |
| 83 | + scheduler: scheduler, |
| 84 | + ipTablesHandler: ipTablesHandler, |
| 85 | + nsPlugin: nsPlugin, |
| 86 | + goRoutinesCnt: goRoutinesCnt, |
| 87 | + minRuleCountForPerfRuleAddition: minRuleCountForPerfRuleAddition, |
| 88 | + log: log.NewLogger("ipt-rulechain-descriptor"), |
85 | 89 | }
|
86 | 90 |
|
87 | 91 | typedDescr := &adapter.RuleChainDescriptor{
|
@@ -208,11 +212,43 @@ func (d *RuleChainDescriptor) Create(key string, rch *linux_iptables.RuleChain)
|
208 | 212 | }
|
209 | 213 |
|
210 | 214 | // append all rules
|
211 |
| - for _, rule := range rch.Rules { |
212 |
| - err := d.ipTablesHandler.AppendRule(protocolType(rch), tableNameStr(rch), chainNameStr(rch), rule) |
213 |
| - if err != nil { |
214 |
| - d.log.Errorf("Error by appending iptables rule: %v", err) |
215 |
| - break |
| 215 | + if len(rch.Rules) > 0 { |
| 216 | + if len(rch.Rules) < d.minRuleCountForPerfRuleAddition { // use normal method of addition |
| 217 | + for _, rule := range rch.Rules { |
| 218 | + err := d.ipTablesHandler.AppendRule(protocolType(rch), tableNameStr(rch), chainNameStr(rch), rule) |
| 219 | + if err != nil { |
| 220 | + d.log.Errorf("Error by appending iptables rule: %v", err) |
| 221 | + break |
| 222 | + } |
| 223 | + } |
| 224 | + } else { // use performance solution (this makes performance difference with higher count of appended rules) |
| 225 | + // export existing iptables data |
| 226 | + data, err := d.ipTablesHandler.SaveTable(protocolType(rch), tableNameStr(rch), true) |
| 227 | + if err != nil { |
| 228 | + return nil, errors.Errorf("Error by adding rules: Can't export all rules due to: %v", err) |
| 229 | + } |
| 230 | + |
| 231 | + // add rules to exported data |
| 232 | + insertPoint := bytes.Index(data, []byte("COMMIT")) |
| 233 | + if insertPoint == -1 { |
| 234 | + return nil, errors.Errorf("Error by adding rules: Can't find COMMIT statement in iptables-save data") |
| 235 | + } |
| 236 | + var rules strings.Builder |
| 237 | + chain := chainNameStr(rch) |
| 238 | + for _, rule := range rch.Rules { |
| 239 | + rules.WriteString(fmt.Sprintf("[0:0] -A %s %s\n", chain, rule)) |
| 240 | + } |
| 241 | + insertData := []byte(rules.String()) |
| 242 | + updatedData := make([]byte, len(data)+len(insertData)) |
| 243 | + copy(updatedData[:insertPoint], data[:insertPoint]) |
| 244 | + copy(updatedData[insertPoint:insertPoint+len(insertData)], insertData) |
| 245 | + copy(updatedData[insertPoint+len(insertData):], data[insertPoint:]) |
| 246 | + |
| 247 | + // import modified data to linux |
| 248 | + err = d.ipTablesHandler.RestoreTable(protocolType(rch), tableNameStr(rch), updatedData, true, true) |
| 249 | + if err != nil { |
| 250 | + return nil, errors.Errorf("Error by adding rules: Can't restore modified iptables data due to: %v", err) |
| 251 | + } |
216 | 252 | }
|
217 | 253 | }
|
218 | 254 |
|
|
0 commit comments