diff --git a/drivers/vppd/vppdriver.go b/drivers/vppd/vppdriver.go index e20d3f44e..5cd0d8302 100644 --- a/drivers/vppd/vppdriver.go +++ b/drivers/vppd/vppdriver.go @@ -20,17 +20,18 @@ import ( "fmt" "hash/fnv" "os" + "strconv" "sync" "time" "github.com/contiv/netplugin/core" "github.com/contiv/netplugin/drivers" "github.com/contiv/netplugin/netmaster/mastercfg" + "github.com/contiv/ofnet" + agent_core "github.com/ligato/cn-infra/core" "github.com/ligato/cn-infra/logging" log "github.com/ligato/cn-infra/logging/logrus" - - agent_core "github.com/ligato/cn-infra/core" "github.com/ligato/vpp-agent/clientv1/linux/localclient" "github.com/ligato/vpp-agent/flavours/linuxlocal" vpp_acl "github.com/ligato/vpp-agent/plugins/defaultplugins/aclplugin/model/acl" @@ -67,7 +68,7 @@ type VppDriverOperState struct { localNetConfigMutex sync.Mutex LocalEpConfig map[string]EndpointConfig // Endpoint ID -> Endpoint config localEpConfigMutex sync.Mutex - LocalACLConfig map[string]ACLConfig // ACL ID -> ACL config + LocalACLConfig map[int][]*ofnet.OfnetPolicyRule // ACL ID -> ACL config localACLConfigMutex sync.Mutex } @@ -129,7 +130,7 @@ func (d *VppDriver) Init(info *core.InstanceInfo) error { d.oper.LocalNetConfig = make(map[string]NetworkConfig) d.oper.LocalEpConfig = make(map[string]EndpointConfig) - d.oper.LocalACLConfig = make(map[string]ACLConfig) + d.oper.LocalACLConfig = make(map[int][]*ofnet.OfnetPolicyRule) // write the oper err = d.oper.Write() @@ -154,7 +155,7 @@ func (d *VppDriver) Init(info *core.InstanceInfo) error { // make sure LocalACLConfig exist if d.oper.LocalACLConfig == nil { - d.oper.LocalACLConfig = make(map[string]ACLConfig) + d.oper.LocalACLConfig = make(map[int][]*ofnet.OfnetPolicyRule) rewriteOper = true } @@ -368,11 +369,28 @@ func (d *VppDriver) CreateEndpoint(id string) error { VppInterface(epcfg.afpacket). Send(). ReceiveReply() + if err != nil { netcfg.bd.Interfaces = origBfIfs log.Errorf("Failed to create endpoint id='%s', Err: %v", id, err) return err } + + // Apply policy if any at the endpoint + d.oper.localACLConfigMutex.Lock() + defer d.oper.localACLConfigMutex.Unlock() + rule, epPolicyCfgExists := d.oper.LocalACLConfig[cfgEp.EndpointGroupID] + if !epPolicyCfgExists { + log.Infof("No policy currently applied to the interface") + } else { + // Add policy to endpoint if exists + err = addEndpointACL(rule, cfgEp.EndpointGroupID, afPacketName) + if err != nil { + log.Errorf("Failed to create endpoint id='%s', Err: %v", id, err) + return err + } + } + // Store the endpoint configuration d.oper.localEpConfigMutex.Lock() defer d.oper.localEpConfigMutex.Unlock() @@ -402,6 +420,7 @@ func (d *VppDriver) CreateEndpoint(id string) error { operEp.Clear() } }() + return nil } @@ -616,109 +635,20 @@ func (d *VppDriver) AddPolicyRule(id string) error { return err } - d.oper.localACLConfigMutex.Lock() - defer d.oper.localACLConfigMutex.Unlock() - _, exists := d.oper.LocalACLConfig[id] - if exists { - err = fmt.Errorf("ACL id='%s' is already configured", id) - log.Error(err.Error()) - return err - } - + log.Infof("EPGID = %d", ruleCfg.EndpointGroupID) + epgID := ruleCfg.EndpointGroupID vppRule := &ruleCfg.OfnetPolicyRule log.Infof("Add policy rule with id='%s' and config: %+v", id, vppRule) - aclcfg := ACLConfig{} - var action *vpp_acl.AccessLists_Acl_Rule_Actions - var matches *vpp_acl.AccessLists_Acl_Rule_Matches - - // Action rule to be VPP specific - if vppRule.Action == "allow" { - action = &vpp_acl.AccessLists_Acl_Rule_Actions{ - AclAction: vpp_acl.AclAction_PERMIT, - } - } else if vppRule.Action == "deny" { - action = &vpp_acl.AccessLists_Acl_Rule_Actions{ - AclAction: vpp_acl.AclAction_DENY, - } - } - - // Src/DstNetwork choice based on protocol - if vppRule.IpProtocol == 6 { - matches = &vpp_acl.AccessLists_Acl_Rule_Matches{ - IpRule: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule{ - Ip: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule_Ip{ - DestinationNetwork: vppRule.DstIpAddr, - SourceNetwork: vppRule.SrcIpAddr, - }, - Tcp: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule_Tcp{ - DestinationPortRange: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule_Tcp_DestinationPortRange{ - LowerPort: uint32(vppRule.DstPort), - UpperPort: uint32(vppRule.DstPort), - }, - SourcePortRange: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule_Tcp_SourcePortRange{ - LowerPort: uint32(vppRule.SrcPort), - UpperPort: uint32(vppRule.SrcPort), - }, - }, - }, - } - } else if vppRule.IpProtocol == 17 { - matches = &vpp_acl.AccessLists_Acl_Rule_Matches{ - IpRule: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule{ - Ip: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule_Ip{ - DestinationNetwork: vppRule.DstIpAddr, - SourceNetwork: vppRule.SrcIpAddr, - }, - Udp: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule_Udp{ - DestinationPortRange: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule_Udp_DestinationPortRange{ - LowerPort: uint32(vppRule.DstPort), - UpperPort: uint32(vppRule.DstPort), - }, - SourcePortRange: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule_Udp_SourcePortRange{ - LowerPort: uint32(vppRule.SrcPort), - UpperPort: uint32(vppRule.SrcPort), - }, - }, - }, - } - } else { - matches = &vpp_acl.AccessLists_Acl_Rule_Matches{ - IpRule: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule{ - Ip: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule_Ip{ - DestinationNetwork: vppRule.DstIpAddr, - SourceNetwork: vppRule.SrcIpAddr, - }, - }, - } - } - - aclcfg.acl = &vpp_acl.AccessLists_Acl{ - AclName: "acl-" + id, - Rules: []*vpp_acl.AccessLists_Acl_Rule{ - { - RuleName: vppRule.RuleId, - Actions: action, - Matches: matches, - }, - }, - } - - log.Info("ACL config: ", aclcfg) - - err = localclient.DataChangeRequest(vppDriverID). - Put(). - ACL(aclcfg.acl). - Send(). - ReceiveReply() - + // save local endpoint info + d.oper.localACLConfigMutex.Lock() + d.oper.LocalACLConfig[epgID] = append(d.oper.LocalACLConfig[epgID], vppRule) + d.oper.localACLConfigMutex.Unlock() + err = d.oper.Write() if err != nil { - log.Errorf("Failed to create policy rule id='%s', Err: %v", id, err) return err } - // Store the network configuration - d.oper.LocalACLConfig[id] = aclcfg return nil } @@ -751,3 +681,110 @@ func genNetworkVNI(netID string) uint32 { } return vni } + +func addEndpointACL(rule []*ofnet.OfnetPolicyRule, epGroupID int, afPacketName string) error { + aclcfg := ACLConfig{} + var action *vpp_acl.AccessLists_Acl_Rule_Actions + var matches *vpp_acl.AccessLists_Acl_Rule_Matches + var interfaces *vpp_acl.AccessLists_Acl_Interfaces + + for id, vppRule := range rule { + ruleID := vppRule.RuleId + epPolicyIf := []string{afPacketName} + + if ruleID[len(ruleID)-2:] == "Rx" { + interfaces = &vpp_acl.AccessLists_Acl_Interfaces{ + Egress: epPolicyIf, + } + } else { + interfaces = &vpp_acl.AccessLists_Acl_Interfaces{ + Ingress: epPolicyIf, + } + } + + // Action rule to be VPP specific + if vppRule.Action == "allow" { + action = &vpp_acl.AccessLists_Acl_Rule_Actions{ + AclAction: vpp_acl.AclAction_PERMIT, + } + } else if vppRule.Action == "deny" { + action = &vpp_acl.AccessLists_Acl_Rule_Actions{ + AclAction: vpp_acl.AclAction_DENY, + } + } + + // Src/DstNetwork choice based on protocol + if vppRule.IpProtocol == 6 { + matches = &vpp_acl.AccessLists_Acl_Rule_Matches{ + IpRule: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule{ + Ip: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule_Ip{ + DestinationNetwork: vppRule.DstIpAddr, + SourceNetwork: vppRule.SrcIpAddr, + }, + Tcp: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule_Tcp{ + DestinationPortRange: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule_Tcp_DestinationPortRange{ + LowerPort: uint32(vppRule.DstPort), + UpperPort: uint32(vppRule.DstPort), + }, + SourcePortRange: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule_Tcp_SourcePortRange{ + LowerPort: uint32(vppRule.SrcPort), + UpperPort: uint32(vppRule.SrcPort), + }, + }, + }, + } + } else if vppRule.IpProtocol == 17 { + matches = &vpp_acl.AccessLists_Acl_Rule_Matches{ + IpRule: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule{ + Ip: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule_Ip{ + DestinationNetwork: vppRule.DstIpAddr, + SourceNetwork: vppRule.SrcIpAddr, + }, + Udp: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule_Udp{ + DestinationPortRange: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule_Udp_DestinationPortRange{ + LowerPort: uint32(vppRule.DstPort), + UpperPort: uint32(vppRule.DstPort), + }, + SourcePortRange: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule_Udp_SourcePortRange{ + LowerPort: uint32(vppRule.SrcPort), + UpperPort: uint32(vppRule.SrcPort), + }, + }, + }, + } + } else { + matches = &vpp_acl.AccessLists_Acl_Rule_Matches{ + IpRule: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule{ + Ip: &vpp_acl.AccessLists_Acl_Rule_Matches_IpRule_Ip{ + DestinationNetwork: vppRule.DstIpAddr, + SourceNetwork: vppRule.SrcIpAddr, + }, + }, + } + } + + aclcfg.acl = &vpp_acl.AccessLists_Acl{ + AclName: "acl-" + vppRule.RuleId[0:7] + "-id-" + strconv.Itoa(id) + afPacketName + "-" + ruleID[len(ruleID)-2:], + Rules: []*vpp_acl.AccessLists_Acl_Rule{ + { + RuleName: vppRule.RuleId + strconv.Itoa(id), + Actions: action, + Matches: matches, + }, + }, + Interfaces: interfaces, + } + + err := localclient.DataChangeRequest(vppDriverID). + Put(). + ACL(aclcfg.acl). + Send(). + ReceiveReply() + + if err != nil { + log.Errorf("Failed to create policy rule id='%s', Err: %v", vppRule.RuleId, err) + return err + } + } + return nil +} diff --git a/netmaster/mastercfg/policyRuleState.go b/netmaster/mastercfg/policyRuleState.go index 0479f076a..2501391f2 100755 --- a/netmaster/mastercfg/policyRuleState.go +++ b/netmaster/mastercfg/policyRuleState.go @@ -32,6 +32,7 @@ const ( type CfgPolicyRule struct { core.CommonState ofnet.OfnetPolicyRule + EndpointGroupID int // Endpoint group where this policy is attached to } // Write the state. @@ -64,10 +65,11 @@ func (s *CfgPolicyRule) Clear() error { } // addPolicyRuleState adds policy rule to state store -func addPolicyRuleState(ofnetRule *ofnet.OfnetPolicyRule) error { +func addPolicyRuleState(ofnetRule *ofnet.OfnetPolicyRule, epgID int) error { ruleCfg := &CfgPolicyRule{} ruleCfg.StateDriver = stateStore ruleCfg.OfnetPolicyRule = (*ofnetRule) + ruleCfg.EndpointGroupID = epgID // Save the rule return ruleCfg.Write() diff --git a/netmaster/mastercfg/policyState.go b/netmaster/mastercfg/policyState.go index 495b04442..7161e9178 100644 --- a/netmaster/mastercfg/policyState.go +++ b/netmaster/mastercfg/policyState.go @@ -294,7 +294,7 @@ func (gp *EpgPolicy) createOfnetRule(rule *contivModel.Rule, dir string) (*ofnet // } // Send AddRule to netplugin agents - err = addPolicyRuleState(ofnetRule) + err = addPolicyRuleState(ofnetRule, gp.EndpointGroupID) if err != nil { log.Errorf("Error creating rule {%+v}. Err: %v", ofnetRule, err) return nil, err @@ -380,7 +380,7 @@ func (gp *EpgPolicy) DelRule(rule *contivModel.Rule) error { // } // Send DelRule to netplugin agents - err = delPolicyRuleState(ofnetRule) + err := delPolicyRuleState(ofnetRule) if err != nil { log.Errorf("Error deleting the ofnet rule {%+v}. Err: %v", ofnetRule, err) }