-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
TC generator generates TC objects based on PolicyRuleSet - Add Generator interface - Add SimpleTCGenerator a Generator implementation Signed-off-by: Adrian Chiris <[email protected]>
- Loading branch information
1 parent
30408e2
commit 8932114
Showing
1 changed file
with
159 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
package tc | ||
|
||
import ( | ||
"fmt" | ||
"net" | ||
|
||
"github.com/pkg/errors" | ||
|
||
"github.com/Mellanox/multi-networkpolicy-tc/pkg/policyrules" | ||
tctypes "github.com/Mellanox/multi-networkpolicy-tc/pkg/tc/types" | ||
) | ||
|
||
const ( | ||
PrioDefault = 300 | ||
PrioPass = 200 | ||
PrioDrop = 100 | ||
) | ||
|
||
// TCObjects is a struct containing TC objects | ||
type TCObjects struct { | ||
// QDisc is the TC QDisc where rules should be applied | ||
QDisc tctypes.QDisc | ||
// Filters are the TC filters that should be applied | ||
Filters []tctypes.Filter | ||
} | ||
|
||
// TCGenerator is an interface to generate TCObjects from PolicyRuleSet | ||
type TCGenerator interface { | ||
// GenerateFromPolicyRuleSet creates TCObjects that correspond to the provided ruleSet | ||
GenerateFromPolicyRuleSet(ruleSet policyrules.PolicyRuleSet) (*TCObjects, error) | ||
} | ||
|
||
// NewSimpleTCGenerator creates a new SimpleTCGenerator instance | ||
func NewSimpleTCGenerator() *SimpleTCGenerator { | ||
return &SimpleTCGenerator{} | ||
} | ||
|
||
// SimpleTCGenerator is a simple implementation for TCGenerator interface | ||
type SimpleTCGenerator struct{} | ||
|
||
// GenerateFromPolicyRuleSet implements TCGenerator interface | ||
// It renders TC objects needed to satisfy the rules in the provided PolicyRuleSet | ||
// QDisc is Ingress QDisc | ||
// Filters is a list of filters which satisfy the PolicyRuleSet. They are generated as follows | ||
// 1. Drop rule at chain 0, priority 300 for all traffic | ||
// 2. Accept rules per CIDR X Port for every Pass Rule in PolicyRuleSet at chain 0, priority 200 | ||
// 3. Drop rules per CIDR X Port for every Drop Rule in PolicyRuleSet at chain 0, prioirty 100 | ||
// Note: only Egress Policy type is supported | ||
func (s *SimpleTCGenerator) GenerateFromPolicyRuleSet(ruleSet policyrules.PolicyRuleSet) (*TCObjects, error) { | ||
tcObj := &TCObjects{ | ||
QDisc: nil, | ||
Filters: make([]tctypes.Filter, 0), | ||
} | ||
// only egress policy is supported | ||
if ruleSet.Type != policyrules.PolicyTypeEgress { | ||
return nil, fmt.Errorf("unsupported policy type. %s", ruleSet.Type) | ||
} | ||
|
||
// create qdisc obj | ||
tcObj.QDisc = tctypes.NewIngressQdisc() | ||
|
||
if ruleSet.Rules == nil { | ||
// no rules | ||
return tcObj, nil | ||
} | ||
|
||
// create filters | ||
// 1. default drop rule at priority 300 | ||
defaultDropFliter := tctypes.NewFlowerFilterBuilder(). | ||
WithPriority(PrioDefault). | ||
WithProtocol(tctypes.FilterProtocolIP). | ||
WithAction(tctypes.NewGenericActionBuiler().WithDrop().Build()). | ||
Build() | ||
tcObj.Filters = append(tcObj.Filters, defaultDropFliter) | ||
|
||
for _, rule := range ruleSet.Rules { | ||
// 2. accept rules at priority 200 | ||
// 3. drop rules at priority 100 | ||
if rule.Action == policyrules.PolicyActionPass { | ||
passFilters, err := s.genPassFilters(rule) | ||
if err != nil { | ||
return nil, errors.Wrapf(err, "failed to generate filters") | ||
} | ||
tcObj.Filters = append(tcObj.Filters, passFilters...) | ||
} else if rule.Action == policyrules.PolicyActionDrop { | ||
dropFilters, err := s.genDropFilters(rule) | ||
if err != nil { | ||
return nil, errors.Wrapf(err, "failed to generate filters") | ||
} | ||
tcObj.Filters = append(tcObj.Filters, dropFilters...) | ||
} else { | ||
return nil, fmt.Errorf("unknown policy action for rule. %s", rule.Action) | ||
} | ||
} | ||
return tcObj, nil | ||
} | ||
|
||
// genPassFilters generates Filters with Pass action | ||
func (s *SimpleTCGenerator) genPassFilters(rule policyrules.Rule) ([]tctypes.Filter, error) { | ||
return s.genFilters(rule.IPCidrs, rule.Ports, PrioPass, tctypes.NewGenericActionBuiler().WithPass().Build()) | ||
} | ||
|
||
// genPassFilters generates Filters with Drop action | ||
func (s *SimpleTCGenerator) genDropFilters(rule policyrules.Rule) ([]tctypes.Filter, error) { | ||
return s.genFilters(rule.IPCidrs, rule.Ports, PrioDrop, tctypes.NewGenericActionBuiler().WithDrop().Build()) | ||
} | ||
|
||
// genFilters generates (flower) Filters based on provided ipCidrs, ports on the given prio with the given action | ||
// the filters generated are: matching on {ipCidrs} [X {Ports}] With priority `prio`, and action `action` | ||
func (s *SimpleTCGenerator) genFilters(ipCidrs []*net.IPNet, ports []policyrules.Port, prio uint16, action tctypes.Action) ([]tctypes.Filter, error) { | ||
hasIPs := len(ipCidrs) > 0 | ||
hasPorts := len(ports) > 0 | ||
filters := make([]tctypes.Filter, 0) | ||
if hasIPs { | ||
for _, ipCidr := range ipCidrs { | ||
if hasPorts { | ||
for _, port := range ports { | ||
filters = append(filters, | ||
tctypes.NewFlowerFilterBuilder(). | ||
WithProtocol(tctypes.FilterProtocolIP). | ||
WithPriority(prio). | ||
WithMatchKeyDstIP(ipCidr.String()). | ||
WithMatchKeyIPProto(port.Protocol). | ||
WithMatchKeyDstPort(port.Number). | ||
WithAction(action). | ||
Build()) | ||
} | ||
} else { | ||
filters = append(filters, | ||
tctypes.NewFlowerFilterBuilder(). | ||
WithProtocol(tctypes.FilterProtocolIP). | ||
WithPriority(prio). | ||
WithMatchKeyDstIP(ipCidr.String()). | ||
WithAction(action). | ||
Build()) | ||
} | ||
} | ||
} else if hasPorts { | ||
for _, port := range ports { | ||
filters = append(filters, | ||
tctypes.NewFlowerFilterBuilder(). | ||
WithProtocol(tctypes.FilterProtocolIP). | ||
WithPriority(prio). | ||
WithMatchKeyIPProto(port.Protocol). | ||
WithMatchKeyDstPort(port.Number). | ||
WithAction(action). | ||
Build()) | ||
} | ||
} else { | ||
// match all with action | ||
filters = append(filters, | ||
tctypes.NewFlowerFilterBuilder(). | ||
WithProtocol(tctypes.FilterProtocolIP). | ||
WithPriority(prio). | ||
WithAction(action). | ||
Build()) | ||
} | ||
return filters, nil | ||
} |