diff --git a/calico-vpp-agent/felix/felix_server.go b/calico-vpp-agent/felix/felix_server.go index 8dba9a45f..2e54c72b2 100644 --- a/calico-vpp-agent/felix/felix_server.go +++ b/calico-vpp-agent/felix/felix_server.go @@ -40,6 +40,7 @@ import ( "github.com/projectcalico/vpp-dataplane/v3/calico-vpp-agent/watchers" "github.com/projectcalico/vpp-dataplane/v3/config" "github.com/projectcalico/vpp-dataplane/v3/vpplink" + "github.com/projectcalico/vpp-dataplane/v3/vpplink/generated/bindings/npol" "github.com/projectcalico/vpp-dataplane/v3/vpplink/types" ) @@ -82,6 +83,7 @@ type Server struct { /* workloadToHost may drop traffic that goes from the pods to the host */ workloadsToHostPolicy *Policy defaultTap0IngressConf []uint32 + defaultTap0EgressConf []uint32 /* always allow traffic coming from host to the pods (for healthchecks and so on) */ // AllowFromHostPolicy persists the policy allowing host --> pod communications. // See CreateAllowFromHostPolicy definition @@ -90,9 +92,10 @@ type Server struct { allPodsIpset *IPSet /* allow traffic between uplink/tunnels and tap interfaces */ allowToHostPolicy *Policy - ip4 *net.IP - ip6 *net.IP - interfacesMap map[string]interfaceDetails + /* deny all policy for heps with no policies defined */ + ip4 *net.IP + ip6 *net.IP + interfacesMap map[string]interfaceDetails felixServerEventChan chan common.CalicoVppEvent networkDefinitions map[string]*watchers.NetworkDefinition @@ -953,6 +956,22 @@ func (s *Server) handleHostEndpointUpdate(msg *proto.HostEndpointUpdate, pending // we are not supposed to fallback to expectedIPs if interfaceName doesn't match // this is the current behavior in calico linux s.log.Errorf("cannot find host endpoint: interface named %s does not exist", hep.InterfaceName) + // *************************** this is temporary, for dev + if hep.expectedIPs != nil { + for _, existingIf := range s.interfacesMap { + interfaceFound1: + for _, address := range existingIf.addresses { + for _, expectedIP := range hep.expectedIPs { + if address == expectedIP { + hep.UplinkSwIfIndexes = append(hep.UplinkSwIfIndexes, existingIf.uplinkIndex) + hep.TapSwIfIndexes = append(hep.TapSwIfIndexes, existingIf.tapIndex) + break interfaceFound1 + } + } + } + } + } + // *************************** } } else if hep.InterfaceName == "" && hep.expectedIPs != nil { for _, existingIf := range s.interfacesMap { @@ -1696,24 +1715,10 @@ func (s *Server) createEndpointToHostPolicy( /*may be return*/ ) (err error) { } s.workloadsToHostPolicy = workloadsToHostPolicy - allowAllPol := &Policy{ - Policy: &types.Policy{}, - VppID: types.InvalidID, - InboundRules: []*Rule{ - { - VppID: types.InvalidID, - Rule: &types.Rule{ - Action: types.ActionAllow, - }, - }, - }, - } - err = allowAllPol.Create(s.vpp, &ps) - if err != nil { - return err - } conf := types.NewInterfaceConfig() - conf.IngressPolicyIDs = append(conf.IngressPolicyIDs, s.workloadsToHostPolicy.VppID, allowAllPol.VppID) + conf.IngressPolicyIDs = append(conf.IngressPolicyIDs, s.workloadsToHostPolicy.VppID) + conf.PolicyDefaultTx = npol.NPOL_DEFAULT_ALLOW + conf.PolicyDefaultRx = npol.NPOL_DEFAULT_ALLOW swifindexes, err := s.vpp.SearchInterfacesWithTagPrefix("host-") // tap0 interfaces if err != nil { s.log.Error(err) @@ -1725,6 +1730,7 @@ func (s *Server) createEndpointToHostPolicy( /*may be return*/ ) (err error) { } } s.defaultTap0IngressConf = conf.IngressPolicyIDs + s.defaultTap0EgressConf = conf.EgressPolicyIDs return nil } @@ -1753,7 +1759,7 @@ func (s *Server) createFailSafePolicies() (err error) { DstPortRange: []types.PortRange{{First: protoPort.Port, Last: protoPort.Port}}, Filters: []types.RuleFilter{{ ShouldMatch: true, - Type: types.CapoFilterProto, + Type: types.NpolFilterProto, Value: int(protocol), }}, }, @@ -1787,7 +1793,7 @@ func (s *Server) createFailSafePolicies() (err error) { DstPortRange: []types.PortRange{{First: protoPort.Port, Last: protoPort.Port}}, Filters: []types.RuleFilter{{ ShouldMatch: true, - Type: types.CapoFilterProto, + Type: types.NpolFilterProto, Value: int(protocol), }}, }, diff --git a/calico-vpp-agent/felix/host_endpoint.go b/calico-vpp-agent/felix/host_endpoint.go index cc0248ef7..3cf93d064 100644 --- a/calico-vpp-agent/felix/host_endpoint.go +++ b/calico-vpp-agent/felix/host_endpoint.go @@ -22,6 +22,7 @@ import ( "github.com/projectcalico/calico/felix/proto" "github.com/projectcalico/vpp-dataplane/v3/vpplink" + "github.com/projectcalico/vpp-dataplane/v3/vpplink/generated/bindings/npol" "github.com/projectcalico/vpp-dataplane/v3/vpplink/types" ) @@ -134,7 +135,7 @@ func (h *HostEndpoint) handleTunnelChange(swIfIndex uint32, isAdd bool, pending return err } -func (h *HostEndpoint) getHostPolicies(state *PolicyState, tiers []Tier) (conf *types.InterfaceConfig, err error) { +func (h *HostEndpoint) getUserDefinedPolicies(state *PolicyState, tiers []Tier) (conf *types.InterfaceConfig, err error) { conf = types.NewInterfaceConfig() for _, tier := range tiers { for _, polName := range tier.IngressPolicies { @@ -171,32 +172,70 @@ func (h *HostEndpoint) getHostPolicies(state *PolicyState, tiers []Tier) (conf * return conf, nil } +/* + This function creates the interface configuration for the host, applied on the vpptap0 + interface i.e. the tap interface from VPP to the host + that we use as controlpoint for HostEndpoint implementation + We have an implicit workloadsToHostPolicy policy that controls the traffic from + workloads to their host: it is defined by felixConfig.DefaultEndpointToHostAction + We have an implicit failsafe rules policy defined by felixConfig as well. + + If there are no policies the default should be pass to profiles + If there are policies the default should be deny (profiles are ignored) +*/ func (h *HostEndpoint) getTapPolicies(state *PolicyState) (conf *types.InterfaceConfig, err error) { - conf, err = h.getHostPolicies(state, h.Tiers) + conf, err = h.getUserDefinedPolicies(state, h.Tiers) if err != nil { return nil, errors.Wrap(err, "cannot create host policies for TapConf") } - if len(conf.IngressPolicyIDs) > 0 { - conf.IngressPolicyIDs = append(conf.IngressPolicyIDs, h.server.workloadsToHostPolicy.VppID) + if len(conf.IngressPolicyIDs) == 0 && len(conf.ProfileIDs) == 0 { + // If a host endpoint is created and network policy is not in place, + // the Calico default is to deny traffic to/from that endpoint + // (except for traffic allowed by failsafe rules). + // note: this applies to ingress and egress separately, so if you don't have + // ingress only you drop ingress + conf.IngressPolicyIDs = []uint32{h.server.workloadsToHostPolicy.VppID, h.server.failSafePolicy.VppID} + conf.PolicyDefaultTx = npol.NPOL_DEFAULT_DENY + } else { + if len(conf.IngressPolicyIDs) > 0 { + conf.PolicyDefaultTx = npol.NPOL_DEFAULT_DENY + } else if len(conf.ProfileIDs) > 0 { + conf.PolicyDefaultTx = npol.NPOL_DEFAULT_PASS + } conf.IngressPolicyIDs = append([]uint32{h.server.failSafePolicy.VppID}, conf.IngressPolicyIDs...) + conf.IngressPolicyIDs = append([]uint32{h.server.workloadsToHostPolicy.VppID}, conf.IngressPolicyIDs...) } - if len(conf.EgressPolicyIDs) > 0 { - conf.EgressPolicyIDs = append([]uint32{h.server.AllowFromHostPolicy.VppID}, conf.EgressPolicyIDs...) + if len(conf.EgressPolicyIDs) == 0 && len(conf.ProfileIDs) == 0 { + conf.EgressPolicyIDs = []uint32{h.server.AllowFromHostPolicy.VppID, h.server.failSafePolicy.VppID} + conf.PolicyDefaultRx = npol.NPOL_DEFAULT_DENY + } else { + if len(conf.EgressPolicyIDs) > 0 { + conf.PolicyDefaultRx = npol.NPOL_DEFAULT_DENY + } else if len(conf.ProfileIDs) > 0 { + conf.PolicyDefaultRx = npol.NPOL_DEFAULT_PASS + } conf.EgressPolicyIDs = append([]uint32{h.server.failSafePolicy.VppID}, conf.EgressPolicyIDs...) + conf.EgressPolicyIDs = append([]uint32{h.server.AllowFromHostPolicy.VppID}, conf.EgressPolicyIDs...) } return conf, nil } func (h *HostEndpoint) getForwardPolicies(state *PolicyState) (conf *types.InterfaceConfig, err error) { - conf, err = h.getHostPolicies(state, h.ForwardTiers) + conf, err = h.getUserDefinedPolicies(state, h.ForwardTiers) if err != nil { return nil, errors.Wrap(err, "cannot create host policies for forwardConf") } if len(conf.EgressPolicyIDs) > 0 { conf.EgressPolicyIDs = append([]uint32{h.server.allowToHostPolicy.VppID}, conf.EgressPolicyIDs...) + conf.PolicyDefaultRx = npol.NPOL_DEFAULT_DENY + } else if len(conf.ProfileIDs) > 0 { + conf.PolicyDefaultRx = npol.NPOL_DEFAULT_PASS } if len(conf.IngressPolicyIDs) > 0 { conf.IngressPolicyIDs = append([]uint32{h.server.allowToHostPolicy.VppID}, conf.IngressPolicyIDs...) + conf.PolicyDefaultTx = npol.NPOL_DEFAULT_DENY + } else if len(conf.ProfileIDs) > 0 { + conf.PolicyDefaultTx = npol.NPOL_DEFAULT_PASS } return conf, nil } @@ -273,6 +312,7 @@ func (h *HostEndpoint) Delete(vpp *vpplink.VppLink, state *PolicyState) (err err h.server.log.Infof("policy(del) interface swif=%d", swIfIndex) conf := types.NewInterfaceConfig() conf.IngressPolicyIDs = h.server.defaultTap0IngressConf + conf.EgressPolicyIDs = h.server.defaultTap0EgressConf err = vpp.ConfigurePolicies(swIfIndex, conf, 0) if err != nil { return errors.Wrapf(err, "cannot unconfigure policies on interface %d", swIfIndex) diff --git a/calico-vpp-agent/felix/rule.go b/calico-vpp-agent/felix/rule.go index 9fd61cd8a..9d9fd2e8b 100644 --- a/calico-vpp-agent/felix/rule.go +++ b/calico-vpp-agent/felix/rule.go @@ -123,17 +123,6 @@ func fromProtoRule(r *proto.Rule) (rule *Rule, err error) { return nil, fmt.Errorf("unknown rule action: %s", r.Action) } - switch r.IpVersion { - case proto.IPVersion_ANY: - rule.AddressFamily = types.FamilyAll - case proto.IPVersion_IPV4: - rule.AddressFamily = types.FamilyV4 - case proto.IPVersion_IPV6: - rule.AddressFamily = types.FamilyV6 - default: - return nil, fmt.Errorf("unknown rule AF: %d", r.IpVersion) - } - if r.Protocol != nil { if r.NotProtocol != nil { return nil, fmt.Errorf("protocol and NotProtocol specified in Rule") @@ -144,7 +133,7 @@ func fromProtoRule(r *proto.Rule) (rule *Rule, err error) { } rule.Filters = append(rule.Filters, types.RuleFilter{ ShouldMatch: true, - Type: types.CapoFilterProto, + Type: types.NpolFilterProto, Value: int(proto), }) } @@ -155,7 +144,7 @@ func fromProtoRule(r *proto.Rule) (rule *Rule, err error) { } rule.Filters = append(rule.Filters, types.RuleFilter{ ShouldMatch: false, - Type: types.CapoFilterProto, + Type: types.NpolFilterProto, Value: int(proto), }) } diff --git a/calico-vpp-agent/felix/workload_endpoint.go b/calico-vpp-agent/felix/workload_endpoint.go index 865f3af47..cb0e4f895 100644 --- a/calico-vpp-agent/felix/workload_endpoint.go +++ b/calico-vpp-agent/felix/workload_endpoint.go @@ -22,6 +22,7 @@ import ( "github.com/projectcalico/calico/felix/proto" "github.com/projectcalico/vpp-dataplane/v3/vpplink" + "github.com/projectcalico/vpp-dataplane/v3/vpplink/generated/bindings/npol" "github.com/projectcalico/vpp-dataplane/v3/vpplink/types" ) @@ -87,7 +88,7 @@ func fromProtoWorkload(wep *proto.WorkloadEndpoint, server *Server) *WorkloadEnd return r } -func (w *WorkloadEndpoint) getPolicies(state *PolicyState, network string) (conf *types.InterfaceConfig, err error) { +func (w *WorkloadEndpoint) getUserDefinedPolicies(state *PolicyState, network string) (conf *types.InterfaceConfig, err error) { conf = types.NewInterfaceConfig() for _, tier := range w.Tiers { for _, polName := range tier.IngressPolicies { @@ -121,14 +122,37 @@ func (w *WorkloadEndpoint) getPolicies(state *PolicyState, network string) (conf } conf.ProfileIDs = append(conf.ProfileIDs, prof.VppID) } + return conf, nil +} + +/* + This function creates the interface configuration for a workload (pod) interface + We have an implicit ingress policy that allows traffic coming from the host + see createAllowFromHostPolicy() + If there are no policies the default should be pass to profiles + If there are policies the default should be deny (profiles are ignored) +*/ +func (w *WorkloadEndpoint) getWorkloadPolicies(state *PolicyState, network string) (conf *types.InterfaceConfig, err error) { + conf, err = w.getUserDefinedPolicies(state, network) + if err != nil { + return nil, errors.Wrap(err, "cannot create workload policies") + } if len(conf.IngressPolicyIDs) > 0 { conf.IngressPolicyIDs = append([]uint32{w.server.AllowFromHostPolicy.VppID}, conf.IngressPolicyIDs...) + conf.PolicyDefaultTx = npol.NPOL_DEFAULT_DENY + } else if len(conf.ProfileIDs) > 0 { + conf.PolicyDefaultTx = npol.NPOL_DEFAULT_PASS + } + if len(conf.EgressPolicyIDs) > 0 { + conf.PolicyDefaultRx = npol.NPOL_DEFAULT_DENY + } else if len(conf.ProfileIDs) > 0 { + conf.PolicyDefaultRx = npol.NPOL_DEFAULT_PASS } return conf, nil } func (w *WorkloadEndpoint) Create(vpp *vpplink.VppLink, swIfIndexes []uint32, state *PolicyState, network string) (err error) { - conf, err := w.getPolicies(state, network) + conf, err := w.getWorkloadPolicies(state, network) if err != nil { return err } @@ -144,7 +168,7 @@ func (w *WorkloadEndpoint) Create(vpp *vpplink.VppLink, swIfIndexes []uint32, st } func (w *WorkloadEndpoint) Update(vpp *vpplink.VppLink, new *WorkloadEndpoint, state *PolicyState, network string) (err error) { - conf, err := new.getPolicies(state, network) + conf, err := new.getWorkloadPolicies(state, network) if err != nil { return err } diff --git a/cmd/calicovppctl/main.go b/cmd/calicovppctl/main.go index 492adb1a0..e2ebb1dcf 100755 --- a/cmd/calicovppctl/main.go +++ b/cmd/calicovppctl/main.go @@ -398,14 +398,14 @@ func exportData(k *KubeClient, nodeName string) error { } executeVppCommandGroup(k, exportDir, prefix, node, "Dumping node state", cnatCmds) - // Get CAPO policies - capoCmds := []CommandSpec{ - {"show capo interfaces", node + ".show-capo-interfaces"}, - {"show capo policies verbose", node + ".show-capo-policies"}, - {"show capo rules", node + ".show-capo-rules"}, - {"show capo ipsets", node + ".show-capo-ipsets"}, - } - executeVppCommandGroup(k, exportDir, prefix, node, "Dumping node policies", capoCmds) + // Get NPOL policies + npolCmds := []CommandSpec{ + {"show npol interfaces", node + ".show-npol-interfaces"}, + {"show npol policies verbose", node + ".show-npol-policies"}, + {"show npol rules", node + ".show-npol-rules"}, + {"show npol ipsets", node + ".show-npol-ipsets"}, + } + executeVppCommandGroup(k, exportDir, prefix, node, "Dumping node policies", npolCmds) } // Compress the temporary directory diff --git a/docs/policies/policies_example.md b/docs/policies/policies_example.md index e40c309aa..aa959ebc9 100644 --- a/docs/policies/policies_example.md +++ b/docs/policies/policies_example.md @@ -1,5 +1,155 @@ # Policy usage example +Calico enriches Kubernetes set of policies allowing to have ordering in +policies, deny rules, policies applied to host interfaces, more flexible +match rules. In CalicoVPP, we feed Felix messages to our policy server +(agent component), which then configures VPP to create those policies. + +## Network Policy (npol) Plugin + +We use the vpp npol plugin (network policies) to implement the calico policies. + +### Overview + +The **Network Policy (npol)** plugin provides a programmable policy engine +for applying packet filtering and forwarding rules in VPP. +It allows you to: + +- Create and manage **IP sets** (collections of IPs, subnets, or IP:port +entries). +- Define **rules** to allow, deny, or log traffic based on IPs, prefixes, sets, +ports, and direction. +- Build **policies** from rules and apply them on interfaces in RX (inbound) +and TX (outbound) directions. + +### Quick Start + +This example shows how to configure and apply a network policy on a loopback interface. + +#### Create a loopback interface and configure an IP address + +````bash +$ calicovppctl vppctl -node worker-1 create loopback interface +loop0 +$ calicovppctl vppctl -node worker-1 set interface state loop0 up +$ calicovppctl vppctl -node worker-1 set interface ip address loop0 10.0.0.1/32 +$ calicovppctl vppctl -node worker-1 sh int addr +local0 (dn): +loop0 (up): + L3 10.0.0.1/32 +```` + +#### Explore npol commands + +````bash +$ calicovppctl vppctl -node worker-1 npol ? +npol interface clear npol interface clear [interface | sw_if_index N] +npol interface configure npol interface configure [interface | + sw_if_index N] rx tx + ... +npol ipset add member npol ipset add member [id] [prefix] +npol ipset add npol ipset add [prefix|proto ip port|ip] +npol ipset del member npol ipset del member [id] [prefix] +npol ipset del npol ipset del [id] +npol policy add npol policy add [rx rule_id rule_id ...] + [tx rule_id rule_id ...] [update [id]] +npol policy del npol policy del [id] +npol rule add npol rule add [ip4|ip6] [allow|deny|log|pass] + [filter[==|!=]value][[src|dst][==|!=] + [prefix|set ID|[port-port]]] +npol rule del npol rule del [id] +```` + +#### Create an IP set + +````bash +$ calicovppctl vppctl -node worker-1 npol ipset add 20.0.0.0/24 +npol ipset 0 added +$ calicovppctl vppctl -node worker-1 sh npol ipsets +[ipset#0;prefix;20.0.0.0/24,] +```` + +#### Add rules + +- Rule 0: Deny packets with a source IP in the created set. +- Rule 1: Allow all other packets. + +````bash +$ calicovppctl vppctl -node worker-1 npol rule add ip4 deny src==set0 + npol rule 0 added +$ calicovppctl vppctl -node worker-1 npol rule add ip4 allow + npol rule 1 added +$ calicovppctl vppctl -node worker-1 sh npol rules + [rule#0;deny][src==[ipset#0;prefix;20.0.0.0/24,],] + [rule#1;allow][] +```` + +#### Create a policy + +This policy applies Rule 0 and Rule 1 on RX, +and Rule 1 on TX. + +````bash +$ calicovppctl vppctl -node worker-1 npol policy add rx 0 1 tx 1 +npol policy 0 added +$ calicovppctl vppctl -node worker-1 sh npol policies verbose +[policy#0] + tx:[rule#1;allow][] + rx:[rule#0;deny][src==[ipset#0;prefix;20.0.0.0/24,],] + rx:[rule#1;allow][] +```` + +#### Apply the policy to an interface + +````bash +$ calicovppctl vppctl -node worker-1 npol interface configure loop0 0 +npol interface 1 configured +$ calicovppctl vppctl -node worker-1 sh npol interfaces +Interfaces with policies configured: +[loop0 sw_if_index=1 addr=10.0.0.1] + rx-policy-default:1 rx-profile-default:1 + tx-policy-default:1 tx-profile-default:1 + profiles: + [policy#0] + tx:[rule#1;allow][] + rx:[rule#0;deny][src==[ipset#0;prefix;20.0.0.0/24,],] + rx:[rule#1;allow][] +```` + +### Summary + +- **IP sets** define groups of IPs, prefixes, or IP:port pairs. +- **Rules** define match conditions and actions (allow, deny, log, pass). +- **Policies** group rules per direction (RX/TX). +- **Interfaces** are configured with policies, enforcing filtering in the +datapath. + +This modular design allows fine-grained policy enforcement +directly in VPP with efficient data structures. + +## Troubleshooting policies + +VPP cli allows to look at policies in details, here are the commands for that + +````bash +$ calicovppctl vppctl -node worker-1 + _______ _ _ _____ ___ + __/ __/ _ \ (_)__ | | / / _ \/ _ \ + _/ _// // / / / _ \ | |/ / ___/ ___/ + /_/ /____(_)_/\___/ |___/_/ /_/ + +vpp# sh npol ? + show npol interfaces show npol interfaces + show npol ipsets show npol ipsets + show npol policies show npol policies [verbose] + show npol rules show npol rules +```` + +Basically, `sh npol interfaces` shows everything related to policies and +where they are applied. + +### Example + Let's create two pods: ````bash @@ -39,7 +189,7 @@ ts2 1/1 Running 0 3m41s 11.0.0.67 kind-worker2 If we check ts2 interface we only have the usual allow policies: ````bash -sh capo interfaces +sh npol interfaces ... [tun3 sw_if_index=11 addr=11.0.0.67 addr6=fd20::1cc0:b1ac:ad47:e7c2] profiles: @@ -75,7 +225,7 @@ spec: And recheck interfaces policies ````bash -sh capo interfaces +sh npol interfaces ... [tun3 sw_if_index=11 addr=11.0.0.67 addr6=fd20::1cc0:b1ac:ad47:e7c2] tx: diff --git a/docs/policies/troubleshooting.md b/docs/policies/troubleshooting.md index c065e6138..91b3d5a2d 100644 --- a/docs/policies/troubleshooting.md +++ b/docs/policies/troubleshooting.md @@ -4,7 +4,7 @@ You can show the active policies per interface using the following CLIs. -## Show capo interfaces +## Show npol interfaces This CLI show the resulting policies configured for every interface in VPP. The first IPv4 address of every pod is provided to help identify which pod @@ -20,7 +20,7 @@ on a given interface. Rules are applied top to bottom. is ``PASS`` or when no policies are configured. ````bash -$ calicovppctl vppctl -node worker-1 show capo interfaces +$ calicovppctl vppctl -node worker-1 show npol interfaces Interfaces with policies configured: [tap0 sw_if_index=2 addr=172.18.0.4 addr6=fc00:f853:ccd:e793::4] tx: @@ -36,12 +36,12 @@ Interfaces with policies configured: [policy#6] ```` -## Show capo policies +## Show npol policies This CLI list all the policies that are referenced on interfaces ````console -$ calicovppctl vppctl -node worker-1 show capo policies verbose +$ calicovppctl vppctl -node worker-1 show npol policies verbose [policy#0] tx:[rule#24;allow][src==[ipset#0;ip;11.0.0.1,fd20::97de:47c:45f6:c00,],] [policy#4] @@ -54,12 +54,12 @@ $ calicovppctl vppctl -node worker-1 show capo policies verbose tx:[rule#12;allow][proto==TCP,dst==6443,] ```` -## Show capo rules +## Show npol rules This list rules that are referenced by policies ````console -$ calicovppctl vppctl -node worker-1 show capo rules +$ calicovppctl vppctl -node worker-1 show npol rules [rule#0;allow][src==172.18.0.4/32,src==fc00:f853:ccd:e793::4/128,] [rule#1;allow][] [rule#16;allow][proto==UDP,dst==67,] @@ -71,11 +71,11 @@ $ calicovppctl vppctl -node worker-1 show capo rules [rule#25;allow][dst==[ipset#0;ip;11.0.0.1,fd20::97de:47c:45f6:c00,],] ```` -## Show capo ipset +## Show npol ipset This list ipsets that are referenced by rules. IPsets are just list of IPs ````console -$ calicovppctl vppctl -node worker-1 show capo ipset +$ calicovppctl vppctl -node worker-1 show npol ipset [ipset#0;ip;11.0.0.1,fd20::97de:47c:45f6:c00,] ```` diff --git a/test/scripts/vppdev.sh b/test/scripts/vppdev.sh index c7c081d3c..76094a29e 100755 --- a/test/scripts/vppdev.sh +++ b/test/scripts/vppdev.sh @@ -293,10 +293,10 @@ vppdev_cli_export () NODE=$node vppctl show cnat snat > ${DIR}/${PREFIX}${node}.show-cnat-snat ; greydot printf '\n' greychr "Dumping node '$node' policies..." - NODE=$node vppctl show capo interfaces > ${DIR}/${PREFIX}${node}.show-capo-interfaces ; greydot - NODE=$node vppctl show capo policies verbose > ${DIR}/${PREFIX}${node}.show-capo-policies ; greydot - NODE=$node vppctl show capo rules > ${DIR}/${PREFIX}${node}.show-capo-rules ; greydot - NODE=$node vppctl show capo ipsets > ${DIR}/${PREFIX}${node}.show-capo-ipsets ; greydot + NODE=$node vppctl show npol interfaces > ${DIR}/${PREFIX}${node}.show-npol-interfaces ; greydot + NODE=$node vppctl show npol policies verbose > ${DIR}/${PREFIX}${node}.show-npol-policies ; greydot + NODE=$node vppctl show npol rules > ${DIR}/${PREFIX}${node}.show-npol-rules ; greydot + NODE=$node vppctl show npol ipsets > ${DIR}/${PREFIX}${node}.show-npol-ipsets ; greydot printf '\n' done # By default, compress to archive diff --git a/vpplink/generated/bindings/capo/capo.ba.go b/vpplink/generated/bindings/capo/capo.ba.go deleted file mode 100644 index 0a8a16495..000000000 --- a/vpplink/generated/bindings/capo/capo.ba.go +++ /dev/null @@ -1,1417 +0,0 @@ -// Code generated by GoVPP's binapi-generator. DO NOT EDIT. - -// Package capo contains generated bindings for API file capo.api. -// -// Contents: -// - 4 enums -// - 8 structs -// - 2 unions -// - 24 messages -package capo - -import ( - "strconv" - - _ "github.com/projectcalico/vpp-dataplane/v3/vpplink/generated/bindings/fib_types" - ip_types "github.com/projectcalico/vpp-dataplane/v3/vpplink/generated/bindings/ip_types" - api "go.fd.io/govpp/api" - codec "go.fd.io/govpp/codec" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the GoVPP api package it is being compiled against. -// A compilation error at this line likely means your copy of the -// GoVPP api package needs to be updated. -const _ = api.GoVppAPIPackageIsVersion2 - -const ( - APIFile = "capo" - APIVersion = "0.1.0" - VersionCrc = 0x7ed1a7f5 -) - -// CapoEntryType defines enum 'capo_entry_type'. -type CapoEntryType uint8 - -const ( - CAPO_CIDR CapoEntryType = 0 - CAPO_PORT_RANGE CapoEntryType = 1 - CAPO_PORT_IP_SET CapoEntryType = 2 - CAPO_IP_SET CapoEntryType = 3 -) - -var ( - CapoEntryType_name = map[uint8]string{ - 0: "CAPO_CIDR", - 1: "CAPO_PORT_RANGE", - 2: "CAPO_PORT_IP_SET", - 3: "CAPO_IP_SET", - } - CapoEntryType_value = map[string]uint8{ - "CAPO_CIDR": 0, - "CAPO_PORT_RANGE": 1, - "CAPO_PORT_IP_SET": 2, - "CAPO_IP_SET": 3, - } -) - -func (x CapoEntryType) String() string { - s, ok := CapoEntryType_name[uint8(x)] - if ok { - return s - } - return "CapoEntryType(" + strconv.Itoa(int(x)) + ")" -} - -// CapoIpsetType defines enum 'capo_ipset_type'. -type CapoIpsetType uint8 - -const ( - CAPO_IP CapoIpsetType = 0 - CAPO_IP_AND_PORT CapoIpsetType = 1 - CAPO_NET CapoIpsetType = 2 -) - -var ( - CapoIpsetType_name = map[uint8]string{ - 0: "CAPO_IP", - 1: "CAPO_IP_AND_PORT", - 2: "CAPO_NET", - } - CapoIpsetType_value = map[string]uint8{ - "CAPO_IP": 0, - "CAPO_IP_AND_PORT": 1, - "CAPO_NET": 2, - } -) - -func (x CapoIpsetType) String() string { - s, ok := CapoIpsetType_name[uint8(x)] - if ok { - return s - } - return "CapoIpsetType(" + strconv.Itoa(int(x)) + ")" -} - -// CapoRuleAction defines enum 'capo_rule_action'. -type CapoRuleAction uint8 - -const ( - CAPO_ALLOW CapoRuleAction = 0 - CAPO_DENY CapoRuleAction = 1 - CAPO_LOG CapoRuleAction = 2 - CAPO_PASS CapoRuleAction = 3 -) - -var ( - CapoRuleAction_name = map[uint8]string{ - 0: "CAPO_ALLOW", - 1: "CAPO_DENY", - 2: "CAPO_LOG", - 3: "CAPO_PASS", - } - CapoRuleAction_value = map[string]uint8{ - "CAPO_ALLOW": 0, - "CAPO_DENY": 1, - "CAPO_LOG": 2, - "CAPO_PASS": 3, - } -) - -func (x CapoRuleAction) String() string { - s, ok := CapoRuleAction_name[uint8(x)] - if ok { - return s - } - return "CapoRuleAction(" + strconv.Itoa(int(x)) + ")" -} - -// CapoRuleFilterType defines enum 'capo_rule_filter_type'. -type CapoRuleFilterType uint8 - -const ( - CAPO_RULE_FILTER_NONE_TYPE CapoRuleFilterType = 0 - CAPO_RULE_FILTER_ICMP_TYPE CapoRuleFilterType = 1 - CAPO_RULE_FILTER_ICMP_CODE CapoRuleFilterType = 2 - CAPO_RULE_FILTER_L4_PROTO CapoRuleFilterType = 3 -) - -var ( - CapoRuleFilterType_name = map[uint8]string{ - 0: "CAPO_RULE_FILTER_NONE_TYPE", - 1: "CAPO_RULE_FILTER_ICMP_TYPE", - 2: "CAPO_RULE_FILTER_ICMP_CODE", - 3: "CAPO_RULE_FILTER_L4_PROTO", - } - CapoRuleFilterType_value = map[string]uint8{ - "CAPO_RULE_FILTER_NONE_TYPE": 0, - "CAPO_RULE_FILTER_ICMP_TYPE": 1, - "CAPO_RULE_FILTER_ICMP_CODE": 2, - "CAPO_RULE_FILTER_L4_PROTO": 3, - } -) - -func (x CapoRuleFilterType) String() string { - s, ok := CapoRuleFilterType_name[uint8(x)] - if ok { - return s - } - return "CapoRuleFilterType(" + strconv.Itoa(int(x)) + ")" -} - -// CapoEntrySetID defines type 'capo_entry_set_id'. -type CapoEntrySetID struct { - SetID uint32 `binapi:"u32,name=set_id" json:"set_id,omitempty"` -} - -// CapoIpsetMember defines type 'capo_ipset_member'. -type CapoIpsetMember struct { - Val CapoIpsetMemberValUnion `binapi:"capo_ipset_member_val,name=val" json:"val,omitempty"` -} - -// CapoPolicyItem defines type 'capo_policy_item'. -type CapoPolicyItem struct { - IsInbound bool `binapi:"bool,name=is_inbound" json:"is_inbound,omitempty"` - RuleID uint32 `binapi:"u32,name=rule_id" json:"rule_id,omitempty"` -} - -// CapoPortRange defines type 'capo_port_range'. -type CapoPortRange struct { - Start uint16 `binapi:"u16,name=start" json:"start,omitempty"` - End uint16 `binapi:"u16,name=end" json:"end,omitempty"` -} - -// CapoRule defines type 'capo_rule'. -type CapoRule struct { - Af ip_types.AddressFamily `binapi:"address_family,name=af" json:"af,omitempty"` - Action CapoRuleAction `binapi:"capo_rule_action,name=action" json:"action,omitempty"` - Filters [3]CapoRuleFilter `binapi:"capo_rule_filter[3],name=filters" json:"filters,omitempty"` - NumEntries uint32 `binapi:"u32,name=num_entries" json:"-"` - Matches []CapoRuleEntry `binapi:"capo_rule_entry[num_entries],name=matches" json:"matches,omitempty"` -} - -// CapoRuleEntry defines type 'capo_rule_entry'. -type CapoRuleEntry struct { - IsSrc bool `binapi:"bool,name=is_src" json:"is_src,omitempty"` - IsNot bool `binapi:"bool,name=is_not" json:"is_not,omitempty"` - Type CapoEntryType `binapi:"capo_entry_type,name=type" json:"type,omitempty"` - Data CapoEntryDataUnion `binapi:"capo_entry_data,name=data" json:"data,omitempty"` -} - -// CapoRuleFilter defines type 'capo_rule_filter'. -type CapoRuleFilter struct { - Value uint32 `binapi:"u32,name=value" json:"value,omitempty"` - Type CapoRuleFilterType `binapi:"capo_rule_filter_type,name=type" json:"type,omitempty"` - ShouldMatch uint8 `binapi:"u8,name=should_match" json:"should_match,omitempty"` -} - -// CapoThreeTuple defines type 'capo_three_tuple'. -type CapoThreeTuple struct { - Address ip_types.Address `binapi:"address,name=address" json:"address,omitempty"` - L4Proto uint8 `binapi:"u8,name=l4_proto" json:"l4_proto,omitempty"` - Port uint16 `binapi:"u16,name=port" json:"port,omitempty"` -} - -// CapoEntryDataUnion defines union 'capo_entry_data'. -type CapoEntryDataUnion struct { - // CapoEntryDataUnion can be one of: - // - Cidr *ip_types.Prefix - // - PortRange *CapoPortRange - // - SetID *CapoEntrySetID - XXX_UnionData [18]byte -} - -func CapoEntryDataUnionCidr(a ip_types.Prefix) (u CapoEntryDataUnion) { - u.SetCidr(a) - return -} -func (u *CapoEntryDataUnion) SetCidr(a ip_types.Prefix) { - buf := codec.NewBuffer(u.XXX_UnionData[:]) - buf.EncodeUint8(uint8(a.Address.Af)) - buf.EncodeBytes(a.Address.Un.XXX_UnionData[:], 16) - buf.EncodeUint8(a.Len) -} -func (u *CapoEntryDataUnion) GetCidr() (a ip_types.Prefix) { - buf := codec.NewBuffer(u.XXX_UnionData[:]) - a.Address.Af = ip_types.AddressFamily(buf.DecodeUint8()) - copy(a.Address.Un.XXX_UnionData[:], buf.DecodeBytes(16)) - a.Len = buf.DecodeUint8() - return -} - -func CapoEntryDataUnionPortRange(a CapoPortRange) (u CapoEntryDataUnion) { - u.SetPortRange(a) - return -} -func (u *CapoEntryDataUnion) SetPortRange(a CapoPortRange) { - buf := codec.NewBuffer(u.XXX_UnionData[:]) - buf.EncodeUint16(a.Start) - buf.EncodeUint16(a.End) -} -func (u *CapoEntryDataUnion) GetPortRange() (a CapoPortRange) { - buf := codec.NewBuffer(u.XXX_UnionData[:]) - a.Start = buf.DecodeUint16() - a.End = buf.DecodeUint16() - return -} - -func CapoEntryDataUnionSetID(a CapoEntrySetID) (u CapoEntryDataUnion) { - u.SetSetID(a) - return -} -func (u *CapoEntryDataUnion) SetSetID(a CapoEntrySetID) { - buf := codec.NewBuffer(u.XXX_UnionData[:]) - buf.EncodeUint32(a.SetID) -} -func (u *CapoEntryDataUnion) GetSetID() (a CapoEntrySetID) { - buf := codec.NewBuffer(u.XXX_UnionData[:]) - a.SetID = buf.DecodeUint32() - return -} - -// CapoIpsetMemberValUnion defines union 'capo_ipset_member_val'. -type CapoIpsetMemberValUnion struct { - // CapoIpsetMemberValUnion can be one of: - // - Address *ip_types.Address - // - Prefix *ip_types.Prefix - // - Tuple *CapoThreeTuple - XXX_UnionData [20]byte -} - -func CapoIpsetMemberValUnionAddress(a ip_types.Address) (u CapoIpsetMemberValUnion) { - u.SetAddress(a) - return -} -func (u *CapoIpsetMemberValUnion) SetAddress(a ip_types.Address) { - buf := codec.NewBuffer(u.XXX_UnionData[:]) - buf.EncodeUint8(uint8(a.Af)) - buf.EncodeBytes(a.Un.XXX_UnionData[:], 16) -} -func (u *CapoIpsetMemberValUnion) GetAddress() (a ip_types.Address) { - buf := codec.NewBuffer(u.XXX_UnionData[:]) - a.Af = ip_types.AddressFamily(buf.DecodeUint8()) - copy(a.Un.XXX_UnionData[:], buf.DecodeBytes(16)) - return -} - -func CapoIpsetMemberValUnionPrefix(a ip_types.Prefix) (u CapoIpsetMemberValUnion) { - u.SetPrefix(a) - return -} -func (u *CapoIpsetMemberValUnion) SetPrefix(a ip_types.Prefix) { - buf := codec.NewBuffer(u.XXX_UnionData[:]) - buf.EncodeUint8(uint8(a.Address.Af)) - buf.EncodeBytes(a.Address.Un.XXX_UnionData[:], 16) - buf.EncodeUint8(a.Len) -} -func (u *CapoIpsetMemberValUnion) GetPrefix() (a ip_types.Prefix) { - buf := codec.NewBuffer(u.XXX_UnionData[:]) - a.Address.Af = ip_types.AddressFamily(buf.DecodeUint8()) - copy(a.Address.Un.XXX_UnionData[:], buf.DecodeBytes(16)) - a.Len = buf.DecodeUint8() - return -} - -func CapoIpsetMemberValUnionTuple(a CapoThreeTuple) (u CapoIpsetMemberValUnion) { - u.SetTuple(a) - return -} -func (u *CapoIpsetMemberValUnion) SetTuple(a CapoThreeTuple) { - buf := codec.NewBuffer(u.XXX_UnionData[:]) - buf.EncodeUint8(uint8(a.Address.Af)) - buf.EncodeBytes(a.Address.Un.XXX_UnionData[:], 16) - buf.EncodeUint8(a.L4Proto) - buf.EncodeUint16(a.Port) -} -func (u *CapoIpsetMemberValUnion) GetTuple() (a CapoThreeTuple) { - buf := codec.NewBuffer(u.XXX_UnionData[:]) - a.Address.Af = ip_types.AddressFamily(buf.DecodeUint8()) - copy(a.Address.Un.XXX_UnionData[:], buf.DecodeBytes(16)) - a.L4Proto = buf.DecodeUint8() - a.Port = buf.DecodeUint16() - return -} - -// CapoConfigurePolicies defines message 'capo_configure_policies'. -type CapoConfigurePolicies struct { - SwIfIndex uint32 `binapi:"u32,name=sw_if_index" json:"sw_if_index,omitempty"` - NumRxPolicies uint32 `binapi:"u32,name=num_rx_policies" json:"num_rx_policies,omitempty"` - NumTxPolicies uint32 `binapi:"u32,name=num_tx_policies" json:"num_tx_policies,omitempty"` - TotalIds uint32 `binapi:"u32,name=total_ids" json:"-"` - InvertRxTx uint8 `binapi:"u8,name=invert_rx_tx" json:"invert_rx_tx,omitempty"` - PolicyIds []uint32 `binapi:"u32[total_ids],name=policy_ids" json:"policy_ids,omitempty"` -} - -func (m *CapoConfigurePolicies) Reset() { *m = CapoConfigurePolicies{} } -func (*CapoConfigurePolicies) GetMessageName() string { return "capo_configure_policies" } -func (*CapoConfigurePolicies) GetCrcString() string { return "743e3c30" } -func (*CapoConfigurePolicies) GetMessageType() api.MessageType { - return api.RequestMessage -} - -func (m *CapoConfigurePolicies) Size() (size int) { - if m == nil { - return 0 - } - size += 4 // m.SwIfIndex - size += 4 // m.NumRxPolicies - size += 4 // m.NumTxPolicies - size += 4 // m.TotalIds - size += 1 // m.InvertRxTx - size += 4 * len(m.PolicyIds) // m.PolicyIds - return size -} -func (m *CapoConfigurePolicies) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - buf.EncodeUint32(m.SwIfIndex) - buf.EncodeUint32(m.NumRxPolicies) - buf.EncodeUint32(m.NumTxPolicies) - buf.EncodeUint32(uint32(len(m.PolicyIds))) - buf.EncodeUint8(m.InvertRxTx) - for i := 0; i < len(m.PolicyIds); i++ { - var x uint32 - if i < len(m.PolicyIds) { - x = uint32(m.PolicyIds[i]) - } - buf.EncodeUint32(x) - } - return buf.Bytes(), nil -} -func (m *CapoConfigurePolicies) Unmarshal(b []byte) error { - buf := codec.NewBuffer(b) - m.SwIfIndex = buf.DecodeUint32() - m.NumRxPolicies = buf.DecodeUint32() - m.NumTxPolicies = buf.DecodeUint32() - m.TotalIds = buf.DecodeUint32() - m.InvertRxTx = buf.DecodeUint8() - m.PolicyIds = make([]uint32, m.TotalIds) - for i := 0; i < len(m.PolicyIds); i++ { - m.PolicyIds[i] = buf.DecodeUint32() - } - return nil -} - -// CapoConfigurePoliciesReply defines message 'capo_configure_policies_reply'. -type CapoConfigurePoliciesReply struct { - Retval int32 `binapi:"i32,name=retval" json:"retval,omitempty"` -} - -func (m *CapoConfigurePoliciesReply) Reset() { *m = CapoConfigurePoliciesReply{} } -func (*CapoConfigurePoliciesReply) GetMessageName() string { return "capo_configure_policies_reply" } -func (*CapoConfigurePoliciesReply) GetCrcString() string { return "e8d4e804" } -func (*CapoConfigurePoliciesReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} - -func (m *CapoConfigurePoliciesReply) Size() (size int) { - if m == nil { - return 0 - } - size += 4 // m.Retval - return size -} -func (m *CapoConfigurePoliciesReply) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - buf.EncodeInt32(m.Retval) - return buf.Bytes(), nil -} -func (m *CapoConfigurePoliciesReply) Unmarshal(b []byte) error { - buf := codec.NewBuffer(b) - m.Retval = buf.DecodeInt32() - return nil -} - -// Control ping from client to api server request -// CapoControlPing defines message 'capo_control_ping'. -type CapoControlPing struct{} - -func (m *CapoControlPing) Reset() { *m = CapoControlPing{} } -func (*CapoControlPing) GetMessageName() string { return "capo_control_ping" } -func (*CapoControlPing) GetCrcString() string { return "51077d14" } -func (*CapoControlPing) GetMessageType() api.MessageType { - return api.RequestMessage -} - -func (m *CapoControlPing) Size() (size int) { - if m == nil { - return 0 - } - return size -} -func (m *CapoControlPing) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - return buf.Bytes(), nil -} -func (m *CapoControlPing) Unmarshal(b []byte) error { - return nil -} - -// Control ping from the client to the server response -// - retval - return code for the request -// - vpe_pid - the pid of the vpe, returned by the server -// -// CapoControlPingReply defines message 'capo_control_ping_reply'. -type CapoControlPingReply struct { - Retval int32 `binapi:"i32,name=retval" json:"retval,omitempty"` - ClientIndex uint32 `binapi:"u32,name=client_index" json:"client_index,omitempty"` - VpePID uint32 `binapi:"u32,name=vpe_pid" json:"vpe_pid,omitempty"` -} - -func (m *CapoControlPingReply) Reset() { *m = CapoControlPingReply{} } -func (*CapoControlPingReply) GetMessageName() string { return "capo_control_ping_reply" } -func (*CapoControlPingReply) GetCrcString() string { return "f6b0b8ca" } -func (*CapoControlPingReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} - -func (m *CapoControlPingReply) Size() (size int) { - if m == nil { - return 0 - } - size += 4 // m.Retval - size += 4 // m.ClientIndex - size += 4 // m.VpePID - return size -} -func (m *CapoControlPingReply) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - buf.EncodeInt32(m.Retval) - buf.EncodeUint32(m.ClientIndex) - buf.EncodeUint32(m.VpePID) - return buf.Bytes(), nil -} -func (m *CapoControlPingReply) Unmarshal(b []byte) error { - buf := codec.NewBuffer(b) - m.Retval = buf.DecodeInt32() - m.ClientIndex = buf.DecodeUint32() - m.VpePID = buf.DecodeUint32() - return nil -} - -// Get the plugin version -// CapoGetVersion defines message 'capo_get_version'. -type CapoGetVersion struct{} - -func (m *CapoGetVersion) Reset() { *m = CapoGetVersion{} } -func (*CapoGetVersion) GetMessageName() string { return "capo_get_version" } -func (*CapoGetVersion) GetCrcString() string { return "51077d14" } -func (*CapoGetVersion) GetMessageType() api.MessageType { - return api.RequestMessage -} - -func (m *CapoGetVersion) Size() (size int) { - if m == nil { - return 0 - } - return size -} -func (m *CapoGetVersion) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - return buf.Bytes(), nil -} -func (m *CapoGetVersion) Unmarshal(b []byte) error { - return nil -} - -// Reply to get the plugin version -// - major - Incremented every time a known breaking behavior change is introduced -// - minor - Incremented with small changes, may be used to avoid buggy versions -// -// CapoGetVersionReply defines message 'capo_get_version_reply'. -type CapoGetVersionReply struct { - Major uint32 `binapi:"u32,name=major" json:"major,omitempty"` - Minor uint32 `binapi:"u32,name=minor" json:"minor,omitempty"` -} - -func (m *CapoGetVersionReply) Reset() { *m = CapoGetVersionReply{} } -func (*CapoGetVersionReply) GetMessageName() string { return "capo_get_version_reply" } -func (*CapoGetVersionReply) GetCrcString() string { return "9b32cf86" } -func (*CapoGetVersionReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} - -func (m *CapoGetVersionReply) Size() (size int) { - if m == nil { - return 0 - } - size += 4 // m.Major - size += 4 // m.Minor - return size -} -func (m *CapoGetVersionReply) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - buf.EncodeUint32(m.Major) - buf.EncodeUint32(m.Minor) - return buf.Bytes(), nil -} -func (m *CapoGetVersionReply) Unmarshal(b []byte) error { - buf := codec.NewBuffer(b) - m.Major = buf.DecodeUint32() - m.Minor = buf.DecodeUint32() - return nil -} - -// CapoIpsetAddDelMembers defines message 'capo_ipset_add_del_members'. -type CapoIpsetAddDelMembers struct { - SetID uint32 `binapi:"u32,name=set_id" json:"set_id,omitempty"` - IsAdd bool `binapi:"bool,name=is_add" json:"is_add,omitempty"` - Len uint32 `binapi:"u32,name=len" json:"-"` - Members []CapoIpsetMember `binapi:"capo_ipset_member[len],name=members" json:"members,omitempty"` -} - -func (m *CapoIpsetAddDelMembers) Reset() { *m = CapoIpsetAddDelMembers{} } -func (*CapoIpsetAddDelMembers) GetMessageName() string { return "capo_ipset_add_del_members" } -func (*CapoIpsetAddDelMembers) GetCrcString() string { return "e7056d10" } -func (*CapoIpsetAddDelMembers) GetMessageType() api.MessageType { - return api.RequestMessage -} - -func (m *CapoIpsetAddDelMembers) Size() (size int) { - if m == nil { - return 0 - } - size += 4 // m.SetID - size += 1 // m.IsAdd - size += 4 // m.Len - for j1 := 0; j1 < len(m.Members); j1++ { - var s1 CapoIpsetMember - _ = s1 - if j1 < len(m.Members) { - s1 = m.Members[j1] - } - size += 1 * 20 // s1.Val - } - return size -} -func (m *CapoIpsetAddDelMembers) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - buf.EncodeUint32(m.SetID) - buf.EncodeBool(m.IsAdd) - buf.EncodeUint32(uint32(len(m.Members))) - for j0 := 0; j0 < len(m.Members); j0++ { - var v0 CapoIpsetMember // Members - if j0 < len(m.Members) { - v0 = m.Members[j0] - } - buf.EncodeBytes(v0.Val.XXX_UnionData[:], 20) - } - return buf.Bytes(), nil -} -func (m *CapoIpsetAddDelMembers) Unmarshal(b []byte) error { - buf := codec.NewBuffer(b) - m.SetID = buf.DecodeUint32() - m.IsAdd = buf.DecodeBool() - m.Len = buf.DecodeUint32() - m.Members = make([]CapoIpsetMember, m.Len) - for j0 := 0; j0 < len(m.Members); j0++ { - copy(m.Members[j0].Val.XXX_UnionData[:], buf.DecodeBytes(20)) - } - return nil -} - -// CapoIpsetAddDelMembersReply defines message 'capo_ipset_add_del_members_reply'. -type CapoIpsetAddDelMembersReply struct { - Retval int32 `binapi:"i32,name=retval" json:"retval,omitempty"` -} - -func (m *CapoIpsetAddDelMembersReply) Reset() { *m = CapoIpsetAddDelMembersReply{} } -func (*CapoIpsetAddDelMembersReply) GetMessageName() string { - return "capo_ipset_add_del_members_reply" -} -func (*CapoIpsetAddDelMembersReply) GetCrcString() string { return "e8d4e804" } -func (*CapoIpsetAddDelMembersReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} - -func (m *CapoIpsetAddDelMembersReply) Size() (size int) { - if m == nil { - return 0 - } - size += 4 // m.Retval - return size -} -func (m *CapoIpsetAddDelMembersReply) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - buf.EncodeInt32(m.Retval) - return buf.Bytes(), nil -} -func (m *CapoIpsetAddDelMembersReply) Unmarshal(b []byte) error { - buf := codec.NewBuffer(b) - m.Retval = buf.DecodeInt32() - return nil -} - -// CapoIpsetCreate defines message 'capo_ipset_create'. -type CapoIpsetCreate struct { - Type CapoIpsetType `binapi:"capo_ipset_type,name=type" json:"type,omitempty"` -} - -func (m *CapoIpsetCreate) Reset() { *m = CapoIpsetCreate{} } -func (*CapoIpsetCreate) GetMessageName() string { return "capo_ipset_create" } -func (*CapoIpsetCreate) GetCrcString() string { return "69150c8a" } -func (*CapoIpsetCreate) GetMessageType() api.MessageType { - return api.RequestMessage -} - -func (m *CapoIpsetCreate) Size() (size int) { - if m == nil { - return 0 - } - size += 1 // m.Type - return size -} -func (m *CapoIpsetCreate) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - buf.EncodeUint8(uint8(m.Type)) - return buf.Bytes(), nil -} -func (m *CapoIpsetCreate) Unmarshal(b []byte) error { - buf := codec.NewBuffer(b) - m.Type = CapoIpsetType(buf.DecodeUint8()) - return nil -} - -// CapoIpsetCreateReply defines message 'capo_ipset_create_reply'. -type CapoIpsetCreateReply struct { - Retval int32 `binapi:"i32,name=retval" json:"retval,omitempty"` - SetID uint32 `binapi:"u32,name=set_id" json:"set_id,omitempty"` -} - -func (m *CapoIpsetCreateReply) Reset() { *m = CapoIpsetCreateReply{} } -func (*CapoIpsetCreateReply) GetMessageName() string { return "capo_ipset_create_reply" } -func (*CapoIpsetCreateReply) GetCrcString() string { return "6a43f193" } -func (*CapoIpsetCreateReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} - -func (m *CapoIpsetCreateReply) Size() (size int) { - if m == nil { - return 0 - } - size += 4 // m.Retval - size += 4 // m.SetID - return size -} -func (m *CapoIpsetCreateReply) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - buf.EncodeInt32(m.Retval) - buf.EncodeUint32(m.SetID) - return buf.Bytes(), nil -} -func (m *CapoIpsetCreateReply) Unmarshal(b []byte) error { - buf := codec.NewBuffer(b) - m.Retval = buf.DecodeInt32() - m.SetID = buf.DecodeUint32() - return nil -} - -// CapoIpsetDelete defines message 'capo_ipset_delete'. -type CapoIpsetDelete struct { - SetID uint32 `binapi:"u32,name=set_id" json:"set_id,omitempty"` -} - -func (m *CapoIpsetDelete) Reset() { *m = CapoIpsetDelete{} } -func (*CapoIpsetDelete) GetMessageName() string { return "capo_ipset_delete" } -func (*CapoIpsetDelete) GetCrcString() string { return "ceacdbcb" } -func (*CapoIpsetDelete) GetMessageType() api.MessageType { - return api.RequestMessage -} - -func (m *CapoIpsetDelete) Size() (size int) { - if m == nil { - return 0 - } - size += 4 // m.SetID - return size -} -func (m *CapoIpsetDelete) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - buf.EncodeUint32(m.SetID) - return buf.Bytes(), nil -} -func (m *CapoIpsetDelete) Unmarshal(b []byte) error { - buf := codec.NewBuffer(b) - m.SetID = buf.DecodeUint32() - return nil -} - -// CapoIpsetDeleteReply defines message 'capo_ipset_delete_reply'. -type CapoIpsetDeleteReply struct { - Retval int32 `binapi:"i32,name=retval" json:"retval,omitempty"` -} - -func (m *CapoIpsetDeleteReply) Reset() { *m = CapoIpsetDeleteReply{} } -func (*CapoIpsetDeleteReply) GetMessageName() string { return "capo_ipset_delete_reply" } -func (*CapoIpsetDeleteReply) GetCrcString() string { return "e8d4e804" } -func (*CapoIpsetDeleteReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} - -func (m *CapoIpsetDeleteReply) Size() (size int) { - if m == nil { - return 0 - } - size += 4 // m.Retval - return size -} -func (m *CapoIpsetDeleteReply) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - buf.EncodeInt32(m.Retval) - return buf.Bytes(), nil -} -func (m *CapoIpsetDeleteReply) Unmarshal(b []byte) error { - buf := codec.NewBuffer(b) - m.Retval = buf.DecodeInt32() - return nil -} - -// CapoPolicyCreate defines message 'capo_policy_create'. -type CapoPolicyCreate struct { - NumItems uint32 `binapi:"u32,name=num_items" json:"-"` - Rules []CapoPolicyItem `binapi:"capo_policy_item[num_items],name=rules" json:"rules,omitempty"` -} - -func (m *CapoPolicyCreate) Reset() { *m = CapoPolicyCreate{} } -func (*CapoPolicyCreate) GetMessageName() string { return "capo_policy_create" } -func (*CapoPolicyCreate) GetCrcString() string { return "f7ed31a8" } -func (*CapoPolicyCreate) GetMessageType() api.MessageType { - return api.RequestMessage -} - -func (m *CapoPolicyCreate) Size() (size int) { - if m == nil { - return 0 - } - size += 4 // m.NumItems - for j1 := 0; j1 < len(m.Rules); j1++ { - var s1 CapoPolicyItem - _ = s1 - if j1 < len(m.Rules) { - s1 = m.Rules[j1] - } - size += 1 // s1.IsInbound - size += 4 // s1.RuleID - } - return size -} -func (m *CapoPolicyCreate) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - buf.EncodeUint32(uint32(len(m.Rules))) - for j0 := 0; j0 < len(m.Rules); j0++ { - var v0 CapoPolicyItem // Rules - if j0 < len(m.Rules) { - v0 = m.Rules[j0] - } - buf.EncodeBool(v0.IsInbound) - buf.EncodeUint32(v0.RuleID) - } - return buf.Bytes(), nil -} -func (m *CapoPolicyCreate) Unmarshal(b []byte) error { - buf := codec.NewBuffer(b) - m.NumItems = buf.DecodeUint32() - m.Rules = make([]CapoPolicyItem, m.NumItems) - for j0 := 0; j0 < len(m.Rules); j0++ { - m.Rules[j0].IsInbound = buf.DecodeBool() - m.Rules[j0].RuleID = buf.DecodeUint32() - } - return nil -} - -// CapoPolicyCreateReply defines message 'capo_policy_create_reply'. -type CapoPolicyCreateReply struct { - Retval int32 `binapi:"i32,name=retval" json:"retval,omitempty"` - PolicyID uint32 `binapi:"u32,name=policy_id" json:"policy_id,omitempty"` -} - -func (m *CapoPolicyCreateReply) Reset() { *m = CapoPolicyCreateReply{} } -func (*CapoPolicyCreateReply) GetMessageName() string { return "capo_policy_create_reply" } -func (*CapoPolicyCreateReply) GetCrcString() string { return "90f27405" } -func (*CapoPolicyCreateReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} - -func (m *CapoPolicyCreateReply) Size() (size int) { - if m == nil { - return 0 - } - size += 4 // m.Retval - size += 4 // m.PolicyID - return size -} -func (m *CapoPolicyCreateReply) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - buf.EncodeInt32(m.Retval) - buf.EncodeUint32(m.PolicyID) - return buf.Bytes(), nil -} -func (m *CapoPolicyCreateReply) Unmarshal(b []byte) error { - buf := codec.NewBuffer(b) - m.Retval = buf.DecodeInt32() - m.PolicyID = buf.DecodeUint32() - return nil -} - -// CapoPolicyDelete defines message 'capo_policy_delete'. -type CapoPolicyDelete struct { - PolicyID uint32 `binapi:"u32,name=policy_id" json:"policy_id,omitempty"` -} - -func (m *CapoPolicyDelete) Reset() { *m = CapoPolicyDelete{} } -func (*CapoPolicyDelete) GetMessageName() string { return "capo_policy_delete" } -func (*CapoPolicyDelete) GetCrcString() string { return "ad833868" } -func (*CapoPolicyDelete) GetMessageType() api.MessageType { - return api.RequestMessage -} - -func (m *CapoPolicyDelete) Size() (size int) { - if m == nil { - return 0 - } - size += 4 // m.PolicyID - return size -} -func (m *CapoPolicyDelete) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - buf.EncodeUint32(m.PolicyID) - return buf.Bytes(), nil -} -func (m *CapoPolicyDelete) Unmarshal(b []byte) error { - buf := codec.NewBuffer(b) - m.PolicyID = buf.DecodeUint32() - return nil -} - -// CapoPolicyDeleteReply defines message 'capo_policy_delete_reply'. -type CapoPolicyDeleteReply struct { - Retval int32 `binapi:"i32,name=retval" json:"retval,omitempty"` -} - -func (m *CapoPolicyDeleteReply) Reset() { *m = CapoPolicyDeleteReply{} } -func (*CapoPolicyDeleteReply) GetMessageName() string { return "capo_policy_delete_reply" } -func (*CapoPolicyDeleteReply) GetCrcString() string { return "e8d4e804" } -func (*CapoPolicyDeleteReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} - -func (m *CapoPolicyDeleteReply) Size() (size int) { - if m == nil { - return 0 - } - size += 4 // m.Retval - return size -} -func (m *CapoPolicyDeleteReply) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - buf.EncodeInt32(m.Retval) - return buf.Bytes(), nil -} -func (m *CapoPolicyDeleteReply) Unmarshal(b []byte) error { - buf := codec.NewBuffer(b) - m.Retval = buf.DecodeInt32() - return nil -} - -// CapoPolicyUpdate defines message 'capo_policy_update'. -type CapoPolicyUpdate struct { - PolicyID uint32 `binapi:"u32,name=policy_id" json:"policy_id,omitempty"` - NumItems uint32 `binapi:"u32,name=num_items" json:"-"` - Rules []CapoPolicyItem `binapi:"capo_policy_item[num_items],name=rules" json:"rules,omitempty"` -} - -func (m *CapoPolicyUpdate) Reset() { *m = CapoPolicyUpdate{} } -func (*CapoPolicyUpdate) GetMessageName() string { return "capo_policy_update" } -func (*CapoPolicyUpdate) GetCrcString() string { return "e2097dd0" } -func (*CapoPolicyUpdate) GetMessageType() api.MessageType { - return api.RequestMessage -} - -func (m *CapoPolicyUpdate) Size() (size int) { - if m == nil { - return 0 - } - size += 4 // m.PolicyID - size += 4 // m.NumItems - for j1 := 0; j1 < len(m.Rules); j1++ { - var s1 CapoPolicyItem - _ = s1 - if j1 < len(m.Rules) { - s1 = m.Rules[j1] - } - size += 1 // s1.IsInbound - size += 4 // s1.RuleID - } - return size -} -func (m *CapoPolicyUpdate) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - buf.EncodeUint32(m.PolicyID) - buf.EncodeUint32(uint32(len(m.Rules))) - for j0 := 0; j0 < len(m.Rules); j0++ { - var v0 CapoPolicyItem // Rules - if j0 < len(m.Rules) { - v0 = m.Rules[j0] - } - buf.EncodeBool(v0.IsInbound) - buf.EncodeUint32(v0.RuleID) - } - return buf.Bytes(), nil -} -func (m *CapoPolicyUpdate) Unmarshal(b []byte) error { - buf := codec.NewBuffer(b) - m.PolicyID = buf.DecodeUint32() - m.NumItems = buf.DecodeUint32() - m.Rules = make([]CapoPolicyItem, m.NumItems) - for j0 := 0; j0 < len(m.Rules); j0++ { - m.Rules[j0].IsInbound = buf.DecodeBool() - m.Rules[j0].RuleID = buf.DecodeUint32() - } - return nil -} - -// CapoPolicyUpdateReply defines message 'capo_policy_update_reply'. -type CapoPolicyUpdateReply struct { - Retval int32 `binapi:"i32,name=retval" json:"retval,omitempty"` -} - -func (m *CapoPolicyUpdateReply) Reset() { *m = CapoPolicyUpdateReply{} } -func (*CapoPolicyUpdateReply) GetMessageName() string { return "capo_policy_update_reply" } -func (*CapoPolicyUpdateReply) GetCrcString() string { return "e8d4e804" } -func (*CapoPolicyUpdateReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} - -func (m *CapoPolicyUpdateReply) Size() (size int) { - if m == nil { - return 0 - } - size += 4 // m.Retval - return size -} -func (m *CapoPolicyUpdateReply) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - buf.EncodeInt32(m.Retval) - return buf.Bytes(), nil -} -func (m *CapoPolicyUpdateReply) Unmarshal(b []byte) error { - buf := codec.NewBuffer(b) - m.Retval = buf.DecodeInt32() - return nil -} - -// // where the packet only needs to match one entry in either category -// CapoRuleCreate defines message 'capo_rule_create'. -type CapoRuleCreate struct { - Rule CapoRule `binapi:"capo_rule,name=rule" json:"rule,omitempty"` -} - -func (m *CapoRuleCreate) Reset() { *m = CapoRuleCreate{} } -func (*CapoRuleCreate) GetMessageName() string { return "capo_rule_create" } -func (*CapoRuleCreate) GetCrcString() string { return "0a2d5fd6" } -func (*CapoRuleCreate) GetMessageType() api.MessageType { - return api.RequestMessage -} - -func (m *CapoRuleCreate) Size() (size int) { - if m == nil { - return 0 - } - size += 1 // m.Rule.Af - size += 1 // m.Rule.Action - for j2 := 0; j2 < 3; j2++ { - size += 4 // m.Rule.Filters[j2].Value - size += 1 // m.Rule.Filters[j2].Type - size += 1 // m.Rule.Filters[j2].ShouldMatch - } - size += 4 // m.Rule.NumEntries - for j2 := 0; j2 < len(m.Rule.Matches); j2++ { - var s2 CapoRuleEntry - _ = s2 - if j2 < len(m.Rule.Matches) { - s2 = m.Rule.Matches[j2] - } - size += 1 // s2.IsSrc - size += 1 // s2.IsNot - size += 1 // s2.Type - size += 1 * 18 // s2.Data - } - return size -} -func (m *CapoRuleCreate) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - buf.EncodeUint8(uint8(m.Rule.Af)) - buf.EncodeUint8(uint8(m.Rule.Action)) - for j1 := 0; j1 < 3; j1++ { - buf.EncodeUint32(m.Rule.Filters[j1].Value) - buf.EncodeUint8(uint8(m.Rule.Filters[j1].Type)) - buf.EncodeUint8(m.Rule.Filters[j1].ShouldMatch) - } - buf.EncodeUint32(uint32(len(m.Rule.Matches))) - for j1 := 0; j1 < len(m.Rule.Matches); j1++ { - var v1 CapoRuleEntry // Matches - if j1 < len(m.Rule.Matches) { - v1 = m.Rule.Matches[j1] - } - buf.EncodeBool(v1.IsSrc) - buf.EncodeBool(v1.IsNot) - buf.EncodeUint8(uint8(v1.Type)) - buf.EncodeBytes(v1.Data.XXX_UnionData[:], 18) - } - return buf.Bytes(), nil -} -func (m *CapoRuleCreate) Unmarshal(b []byte) error { - buf := codec.NewBuffer(b) - m.Rule.Af = ip_types.AddressFamily(buf.DecodeUint8()) - m.Rule.Action = CapoRuleAction(buf.DecodeUint8()) - for j1 := 0; j1 < 3; j1++ { - m.Rule.Filters[j1].Value = buf.DecodeUint32() - m.Rule.Filters[j1].Type = CapoRuleFilterType(buf.DecodeUint8()) - m.Rule.Filters[j1].ShouldMatch = buf.DecodeUint8() - } - m.Rule.NumEntries = buf.DecodeUint32() - m.Rule.Matches = make([]CapoRuleEntry, m.Rule.NumEntries) - for j1 := 0; j1 < len(m.Rule.Matches); j1++ { - m.Rule.Matches[j1].IsSrc = buf.DecodeBool() - m.Rule.Matches[j1].IsNot = buf.DecodeBool() - m.Rule.Matches[j1].Type = CapoEntryType(buf.DecodeUint8()) - copy(m.Rule.Matches[j1].Data.XXX_UnionData[:], buf.DecodeBytes(18)) - } - return nil -} - -// CapoRuleCreateReply defines message 'capo_rule_create_reply'. -type CapoRuleCreateReply struct { - Retval int32 `binapi:"i32,name=retval" json:"retval,omitempty"` - RuleID uint32 `binapi:"u32,name=rule_id" json:"rule_id,omitempty"` -} - -func (m *CapoRuleCreateReply) Reset() { *m = CapoRuleCreateReply{} } -func (*CapoRuleCreateReply) GetMessageName() string { return "capo_rule_create_reply" } -func (*CapoRuleCreateReply) GetCrcString() string { return "b48f8052" } -func (*CapoRuleCreateReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} - -func (m *CapoRuleCreateReply) Size() (size int) { - if m == nil { - return 0 - } - size += 4 // m.Retval - size += 4 // m.RuleID - return size -} -func (m *CapoRuleCreateReply) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - buf.EncodeInt32(m.Retval) - buf.EncodeUint32(m.RuleID) - return buf.Bytes(), nil -} -func (m *CapoRuleCreateReply) Unmarshal(b []byte) error { - buf := codec.NewBuffer(b) - m.Retval = buf.DecodeInt32() - m.RuleID = buf.DecodeUint32() - return nil -} - -// CapoRuleDelete defines message 'capo_rule_delete'. -type CapoRuleDelete struct { - RuleID uint32 `binapi:"u32,name=rule_id" json:"rule_id,omitempty"` -} - -func (m *CapoRuleDelete) Reset() { *m = CapoRuleDelete{} } -func (*CapoRuleDelete) GetMessageName() string { return "capo_rule_delete" } -func (*CapoRuleDelete) GetCrcString() string { return "d19bb6be" } -func (*CapoRuleDelete) GetMessageType() api.MessageType { - return api.RequestMessage -} - -func (m *CapoRuleDelete) Size() (size int) { - if m == nil { - return 0 - } - size += 4 // m.RuleID - return size -} -func (m *CapoRuleDelete) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - buf.EncodeUint32(m.RuleID) - return buf.Bytes(), nil -} -func (m *CapoRuleDelete) Unmarshal(b []byte) error { - buf := codec.NewBuffer(b) - m.RuleID = buf.DecodeUint32() - return nil -} - -// CapoRuleDeleteReply defines message 'capo_rule_delete_reply'. -type CapoRuleDeleteReply struct { - Retval int32 `binapi:"i32,name=retval" json:"retval,omitempty"` -} - -func (m *CapoRuleDeleteReply) Reset() { *m = CapoRuleDeleteReply{} } -func (*CapoRuleDeleteReply) GetMessageName() string { return "capo_rule_delete_reply" } -func (*CapoRuleDeleteReply) GetCrcString() string { return "e8d4e804" } -func (*CapoRuleDeleteReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} - -func (m *CapoRuleDeleteReply) Size() (size int) { - if m == nil { - return 0 - } - size += 4 // m.Retval - return size -} -func (m *CapoRuleDeleteReply) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - buf.EncodeInt32(m.Retval) - return buf.Bytes(), nil -} -func (m *CapoRuleDeleteReply) Unmarshal(b []byte) error { - buf := codec.NewBuffer(b) - m.Retval = buf.DecodeInt32() - return nil -} - -// CapoRuleUpdate defines message 'capo_rule_update'. -type CapoRuleUpdate struct { - RuleID uint32 `binapi:"u32,name=rule_id" json:"rule_id,omitempty"` - Rule CapoRule `binapi:"capo_rule,name=rule" json:"rule,omitempty"` -} - -func (m *CapoRuleUpdate) Reset() { *m = CapoRuleUpdate{} } -func (*CapoRuleUpdate) GetMessageName() string { return "capo_rule_update" } -func (*CapoRuleUpdate) GetCrcString() string { return "a0535ee2" } -func (*CapoRuleUpdate) GetMessageType() api.MessageType { - return api.RequestMessage -} - -func (m *CapoRuleUpdate) Size() (size int) { - if m == nil { - return 0 - } - size += 4 // m.RuleID - size += 1 // m.Rule.Af - size += 1 // m.Rule.Action - for j2 := 0; j2 < 3; j2++ { - size += 4 // m.Rule.Filters[j2].Value - size += 1 // m.Rule.Filters[j2].Type - size += 1 // m.Rule.Filters[j2].ShouldMatch - } - size += 4 // m.Rule.NumEntries - for j2 := 0; j2 < len(m.Rule.Matches); j2++ { - var s2 CapoRuleEntry - _ = s2 - if j2 < len(m.Rule.Matches) { - s2 = m.Rule.Matches[j2] - } - size += 1 // s2.IsSrc - size += 1 // s2.IsNot - size += 1 // s2.Type - size += 1 * 18 // s2.Data - } - return size -} -func (m *CapoRuleUpdate) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - buf.EncodeUint32(m.RuleID) - buf.EncodeUint8(uint8(m.Rule.Af)) - buf.EncodeUint8(uint8(m.Rule.Action)) - for j1 := 0; j1 < 3; j1++ { - buf.EncodeUint32(m.Rule.Filters[j1].Value) - buf.EncodeUint8(uint8(m.Rule.Filters[j1].Type)) - buf.EncodeUint8(m.Rule.Filters[j1].ShouldMatch) - } - buf.EncodeUint32(uint32(len(m.Rule.Matches))) - for j1 := 0; j1 < len(m.Rule.Matches); j1++ { - var v1 CapoRuleEntry // Matches - if j1 < len(m.Rule.Matches) { - v1 = m.Rule.Matches[j1] - } - buf.EncodeBool(v1.IsSrc) - buf.EncodeBool(v1.IsNot) - buf.EncodeUint8(uint8(v1.Type)) - buf.EncodeBytes(v1.Data.XXX_UnionData[:], 18) - } - return buf.Bytes(), nil -} -func (m *CapoRuleUpdate) Unmarshal(b []byte) error { - buf := codec.NewBuffer(b) - m.RuleID = buf.DecodeUint32() - m.Rule.Af = ip_types.AddressFamily(buf.DecodeUint8()) - m.Rule.Action = CapoRuleAction(buf.DecodeUint8()) - for j1 := 0; j1 < 3; j1++ { - m.Rule.Filters[j1].Value = buf.DecodeUint32() - m.Rule.Filters[j1].Type = CapoRuleFilterType(buf.DecodeUint8()) - m.Rule.Filters[j1].ShouldMatch = buf.DecodeUint8() - } - m.Rule.NumEntries = buf.DecodeUint32() - m.Rule.Matches = make([]CapoRuleEntry, m.Rule.NumEntries) - for j1 := 0; j1 < len(m.Rule.Matches); j1++ { - m.Rule.Matches[j1].IsSrc = buf.DecodeBool() - m.Rule.Matches[j1].IsNot = buf.DecodeBool() - m.Rule.Matches[j1].Type = CapoEntryType(buf.DecodeUint8()) - copy(m.Rule.Matches[j1].Data.XXX_UnionData[:], buf.DecodeBytes(18)) - } - return nil -} - -// CapoRuleUpdateReply defines message 'capo_rule_update_reply'. -type CapoRuleUpdateReply struct { - Retval int32 `binapi:"i32,name=retval" json:"retval,omitempty"` -} - -func (m *CapoRuleUpdateReply) Reset() { *m = CapoRuleUpdateReply{} } -func (*CapoRuleUpdateReply) GetMessageName() string { return "capo_rule_update_reply" } -func (*CapoRuleUpdateReply) GetCrcString() string { return "e8d4e804" } -func (*CapoRuleUpdateReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} - -func (m *CapoRuleUpdateReply) Size() (size int) { - if m == nil { - return 0 - } - size += 4 // m.Retval - return size -} -func (m *CapoRuleUpdateReply) Marshal(b []byte) ([]byte, error) { - if b == nil { - b = make([]byte, m.Size()) - } - buf := codec.NewBuffer(b) - buf.EncodeInt32(m.Retval) - return buf.Bytes(), nil -} -func (m *CapoRuleUpdateReply) Unmarshal(b []byte) error { - buf := codec.NewBuffer(b) - m.Retval = buf.DecodeInt32() - return nil -} - -func init() { file_capo_binapi_init() } -func file_capo_binapi_init() { - api.RegisterMessage((*CapoConfigurePolicies)(nil), "capo_configure_policies_743e3c30") - api.RegisterMessage((*CapoConfigurePoliciesReply)(nil), "capo_configure_policies_reply_e8d4e804") - api.RegisterMessage((*CapoControlPing)(nil), "capo_control_ping_51077d14") - api.RegisterMessage((*CapoControlPingReply)(nil), "capo_control_ping_reply_f6b0b8ca") - api.RegisterMessage((*CapoGetVersion)(nil), "capo_get_version_51077d14") - api.RegisterMessage((*CapoGetVersionReply)(nil), "capo_get_version_reply_9b32cf86") - api.RegisterMessage((*CapoIpsetAddDelMembers)(nil), "capo_ipset_add_del_members_e7056d10") - api.RegisterMessage((*CapoIpsetAddDelMembersReply)(nil), "capo_ipset_add_del_members_reply_e8d4e804") - api.RegisterMessage((*CapoIpsetCreate)(nil), "capo_ipset_create_69150c8a") - api.RegisterMessage((*CapoIpsetCreateReply)(nil), "capo_ipset_create_reply_6a43f193") - api.RegisterMessage((*CapoIpsetDelete)(nil), "capo_ipset_delete_ceacdbcb") - api.RegisterMessage((*CapoIpsetDeleteReply)(nil), "capo_ipset_delete_reply_e8d4e804") - api.RegisterMessage((*CapoPolicyCreate)(nil), "capo_policy_create_f7ed31a8") - api.RegisterMessage((*CapoPolicyCreateReply)(nil), "capo_policy_create_reply_90f27405") - api.RegisterMessage((*CapoPolicyDelete)(nil), "capo_policy_delete_ad833868") - api.RegisterMessage((*CapoPolicyDeleteReply)(nil), "capo_policy_delete_reply_e8d4e804") - api.RegisterMessage((*CapoPolicyUpdate)(nil), "capo_policy_update_e2097dd0") - api.RegisterMessage((*CapoPolicyUpdateReply)(nil), "capo_policy_update_reply_e8d4e804") - api.RegisterMessage((*CapoRuleCreate)(nil), "capo_rule_create_0a2d5fd6") - api.RegisterMessage((*CapoRuleCreateReply)(nil), "capo_rule_create_reply_b48f8052") - api.RegisterMessage((*CapoRuleDelete)(nil), "capo_rule_delete_d19bb6be") - api.RegisterMessage((*CapoRuleDeleteReply)(nil), "capo_rule_delete_reply_e8d4e804") - api.RegisterMessage((*CapoRuleUpdate)(nil), "capo_rule_update_a0535ee2") - api.RegisterMessage((*CapoRuleUpdateReply)(nil), "capo_rule_update_reply_e8d4e804") -} - -// Messages returns list of all messages in this module. -func AllMessages() []api.Message { - return []api.Message{ - (*CapoConfigurePolicies)(nil), - (*CapoConfigurePoliciesReply)(nil), - (*CapoControlPing)(nil), - (*CapoControlPingReply)(nil), - (*CapoGetVersion)(nil), - (*CapoGetVersionReply)(nil), - (*CapoIpsetAddDelMembers)(nil), - (*CapoIpsetAddDelMembersReply)(nil), - (*CapoIpsetCreate)(nil), - (*CapoIpsetCreateReply)(nil), - (*CapoIpsetDelete)(nil), - (*CapoIpsetDeleteReply)(nil), - (*CapoPolicyCreate)(nil), - (*CapoPolicyCreateReply)(nil), - (*CapoPolicyDelete)(nil), - (*CapoPolicyDeleteReply)(nil), - (*CapoPolicyUpdate)(nil), - (*CapoPolicyUpdateReply)(nil), - (*CapoRuleCreate)(nil), - (*CapoRuleCreateReply)(nil), - (*CapoRuleDelete)(nil), - (*CapoRuleDeleteReply)(nil), - (*CapoRuleUpdate)(nil), - (*CapoRuleUpdateReply)(nil), - } -} diff --git a/vpplink/generated/bindings/capo/capo_rpc.ba.go b/vpplink/generated/bindings/capo/capo_rpc.ba.go deleted file mode 100644 index 90e8084b4..000000000 --- a/vpplink/generated/bindings/capo/capo_rpc.ba.go +++ /dev/null @@ -1,141 +0,0 @@ -// Code generated by GoVPP's binapi-generator. DO NOT EDIT. - -package capo - -import ( - "context" - - api "go.fd.io/govpp/api" -) - -// RPCService defines RPC service capo. -type RPCService interface { - CapoConfigurePolicies(ctx context.Context, in *CapoConfigurePolicies) (*CapoConfigurePoliciesReply, error) - CapoControlPing(ctx context.Context, in *CapoControlPing) (*CapoControlPingReply, error) - CapoGetVersion(ctx context.Context, in *CapoGetVersion) (*CapoGetVersionReply, error) - CapoIpsetAddDelMembers(ctx context.Context, in *CapoIpsetAddDelMembers) (*CapoIpsetAddDelMembersReply, error) - CapoIpsetCreate(ctx context.Context, in *CapoIpsetCreate) (*CapoIpsetCreateReply, error) - CapoIpsetDelete(ctx context.Context, in *CapoIpsetDelete) (*CapoIpsetDeleteReply, error) - CapoPolicyCreate(ctx context.Context, in *CapoPolicyCreate) (*CapoPolicyCreateReply, error) - CapoPolicyDelete(ctx context.Context, in *CapoPolicyDelete) (*CapoPolicyDeleteReply, error) - CapoPolicyUpdate(ctx context.Context, in *CapoPolicyUpdate) (*CapoPolicyUpdateReply, error) - CapoRuleCreate(ctx context.Context, in *CapoRuleCreate) (*CapoRuleCreateReply, error) - CapoRuleDelete(ctx context.Context, in *CapoRuleDelete) (*CapoRuleDeleteReply, error) - CapoRuleUpdate(ctx context.Context, in *CapoRuleUpdate) (*CapoRuleUpdateReply, error) -} - -type serviceClient struct { - conn api.Connection -} - -func NewServiceClient(conn api.Connection) RPCService { - return &serviceClient{conn} -} - -func (c *serviceClient) CapoConfigurePolicies(ctx context.Context, in *CapoConfigurePolicies) (*CapoConfigurePoliciesReply, error) { - out := new(CapoConfigurePoliciesReply) - err := c.conn.Invoke(ctx, in, out) - if err != nil { - return nil, err - } - return out, api.RetvalToVPPApiError(out.Retval) -} - -func (c *serviceClient) CapoControlPing(ctx context.Context, in *CapoControlPing) (*CapoControlPingReply, error) { - out := new(CapoControlPingReply) - err := c.conn.Invoke(ctx, in, out) - if err != nil { - return nil, err - } - return out, api.RetvalToVPPApiError(out.Retval) -} - -func (c *serviceClient) CapoGetVersion(ctx context.Context, in *CapoGetVersion) (*CapoGetVersionReply, error) { - out := new(CapoGetVersionReply) - err := c.conn.Invoke(ctx, in, out) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *serviceClient) CapoIpsetAddDelMembers(ctx context.Context, in *CapoIpsetAddDelMembers) (*CapoIpsetAddDelMembersReply, error) { - out := new(CapoIpsetAddDelMembersReply) - err := c.conn.Invoke(ctx, in, out) - if err != nil { - return nil, err - } - return out, api.RetvalToVPPApiError(out.Retval) -} - -func (c *serviceClient) CapoIpsetCreate(ctx context.Context, in *CapoIpsetCreate) (*CapoIpsetCreateReply, error) { - out := new(CapoIpsetCreateReply) - err := c.conn.Invoke(ctx, in, out) - if err != nil { - return nil, err - } - return out, api.RetvalToVPPApiError(out.Retval) -} - -func (c *serviceClient) CapoIpsetDelete(ctx context.Context, in *CapoIpsetDelete) (*CapoIpsetDeleteReply, error) { - out := new(CapoIpsetDeleteReply) - err := c.conn.Invoke(ctx, in, out) - if err != nil { - return nil, err - } - return out, api.RetvalToVPPApiError(out.Retval) -} - -func (c *serviceClient) CapoPolicyCreate(ctx context.Context, in *CapoPolicyCreate) (*CapoPolicyCreateReply, error) { - out := new(CapoPolicyCreateReply) - err := c.conn.Invoke(ctx, in, out) - if err != nil { - return nil, err - } - return out, api.RetvalToVPPApiError(out.Retval) -} - -func (c *serviceClient) CapoPolicyDelete(ctx context.Context, in *CapoPolicyDelete) (*CapoPolicyDeleteReply, error) { - out := new(CapoPolicyDeleteReply) - err := c.conn.Invoke(ctx, in, out) - if err != nil { - return nil, err - } - return out, api.RetvalToVPPApiError(out.Retval) -} - -func (c *serviceClient) CapoPolicyUpdate(ctx context.Context, in *CapoPolicyUpdate) (*CapoPolicyUpdateReply, error) { - out := new(CapoPolicyUpdateReply) - err := c.conn.Invoke(ctx, in, out) - if err != nil { - return nil, err - } - return out, api.RetvalToVPPApiError(out.Retval) -} - -func (c *serviceClient) CapoRuleCreate(ctx context.Context, in *CapoRuleCreate) (*CapoRuleCreateReply, error) { - out := new(CapoRuleCreateReply) - err := c.conn.Invoke(ctx, in, out) - if err != nil { - return nil, err - } - return out, api.RetvalToVPPApiError(out.Retval) -} - -func (c *serviceClient) CapoRuleDelete(ctx context.Context, in *CapoRuleDelete) (*CapoRuleDeleteReply, error) { - out := new(CapoRuleDeleteReply) - err := c.conn.Invoke(ctx, in, out) - if err != nil { - return nil, err - } - return out, api.RetvalToVPPApiError(out.Retval) -} - -func (c *serviceClient) CapoRuleUpdate(ctx context.Context, in *CapoRuleUpdate) (*CapoRuleUpdateReply, error) { - out := new(CapoRuleUpdateReply) - err := c.conn.Invoke(ctx, in, out) - if err != nil { - return nil, err - } - return out, api.RetvalToVPPApiError(out.Retval) -} diff --git a/vpplink/generated/bindings/npol/npol.ba.go b/vpplink/generated/bindings/npol/npol.ba.go new file mode 100644 index 000000000..dc1c831a7 --- /dev/null +++ b/vpplink/generated/bindings/npol/npol.ba.go @@ -0,0 +1,1379 @@ +// Code generated by GoVPP's binapi-generator. DO NOT EDIT. + +// Package npol contains generated bindings for API file npol.api. +// +// Contents: +// - 5 enums +// - 8 structs +// - 2 unions +// - 22 messages +package npol + +import ( + "strconv" + + _ "github.com/projectcalico/vpp-dataplane/v3/vpplink/generated/bindings/fib_types" + ip_types "github.com/projectcalico/vpp-dataplane/v3/vpplink/generated/bindings/ip_types" + api "go.fd.io/govpp/api" + codec "go.fd.io/govpp/codec" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the GoVPP api package it is being compiled against. +// A compilation error at this line likely means your copy of the +// GoVPP api package needs to be updated. +const _ = api.GoVppAPIPackageIsVersion2 + +const ( + APIFile = "npol" + APIVersion = "0.1.0" + VersionCrc = 0x79451d1 +) + +// NpolEntryType defines enum 'npol_entry_type'. +type NpolEntryType uint8 + +const ( + NPOL_CIDR NpolEntryType = 0 + NPOL_PORT_RANGE NpolEntryType = 1 + NPOL_PORT_IP_SET NpolEntryType = 2 + NPOL_IP_SET NpolEntryType = 3 +) + +var ( + NpolEntryType_name = map[uint8]string{ + 0: "NPOL_CIDR", + 1: "NPOL_PORT_RANGE", + 2: "NPOL_PORT_IP_SET", + 3: "NPOL_IP_SET", + } + NpolEntryType_value = map[string]uint8{ + "NPOL_CIDR": 0, + "NPOL_PORT_RANGE": 1, + "NPOL_PORT_IP_SET": 2, + "NPOL_IP_SET": 3, + } +) + +func (x NpolEntryType) String() string { + s, ok := NpolEntryType_name[uint8(x)] + if ok { + return s + } + return "NpolEntryType(" + strconv.Itoa(int(x)) + ")" +} + +// NpolIpsetType defines enum 'npol_ipset_type'. +type NpolIpsetType uint8 + +const ( + NPOL_IP NpolIpsetType = 0 + NPOL_IP_AND_PORT NpolIpsetType = 1 + NPOL_NET NpolIpsetType = 2 +) + +var ( + NpolIpsetType_name = map[uint8]string{ + 0: "NPOL_IP", + 1: "NPOL_IP_AND_PORT", + 2: "NPOL_NET", + } + NpolIpsetType_value = map[string]uint8{ + "NPOL_IP": 0, + "NPOL_IP_AND_PORT": 1, + "NPOL_NET": 2, + } +) + +func (x NpolIpsetType) String() string { + s, ok := NpolIpsetType_name[uint8(x)] + if ok { + return s + } + return "NpolIpsetType(" + strconv.Itoa(int(x)) + ")" +} + +// NpolPolicyDefault defines enum 'npol_policy_default'. +type NpolPolicyDefault uint8 + +const ( + NPOL_DEFAULT_ALLOW NpolPolicyDefault = 0 + NPOL_DEFAULT_DENY NpolPolicyDefault = 1 + NPOL_DEFAULT_PASS NpolPolicyDefault = 2 +) + +var ( + NpolPolicyDefault_name = map[uint8]string{ + 0: "NPOL_DEFAULT_ALLOW", + 1: "NPOL_DEFAULT_DENY", + 2: "NPOL_DEFAULT_PASS", + } + NpolPolicyDefault_value = map[string]uint8{ + "NPOL_DEFAULT_ALLOW": 0, + "NPOL_DEFAULT_DENY": 1, + "NPOL_DEFAULT_PASS": 2, + } +) + +func (x NpolPolicyDefault) String() string { + s, ok := NpolPolicyDefault_name[uint8(x)] + if ok { + return s + } + return "NpolPolicyDefault(" + strconv.Itoa(int(x)) + ")" +} + +// NpolRuleAction defines enum 'npol_rule_action'. +type NpolRuleAction uint8 + +const ( + NPOL_ALLOW NpolRuleAction = 0 + NPOL_DENY NpolRuleAction = 1 + NPOL_LOG NpolRuleAction = 2 + NPOL_PASS NpolRuleAction = 3 +) + +var ( + NpolRuleAction_name = map[uint8]string{ + 0: "NPOL_ALLOW", + 1: "NPOL_DENY", + 2: "NPOL_LOG", + 3: "NPOL_PASS", + } + NpolRuleAction_value = map[string]uint8{ + "NPOL_ALLOW": 0, + "NPOL_DENY": 1, + "NPOL_LOG": 2, + "NPOL_PASS": 3, + } +) + +func (x NpolRuleAction) String() string { + s, ok := NpolRuleAction_name[uint8(x)] + if ok { + return s + } + return "NpolRuleAction(" + strconv.Itoa(int(x)) + ")" +} + +// NpolRuleFilterType defines enum 'npol_rule_filter_type'. +type NpolRuleFilterType uint8 + +const ( + NPOL_RULE_FILTER_NONE_TYPE NpolRuleFilterType = 0 + NPOL_RULE_FILTER_ICMP_TYPE NpolRuleFilterType = 1 + NPOL_RULE_FILTER_ICMP_CODE NpolRuleFilterType = 2 + NPOL_RULE_FILTER_L4_PROTO NpolRuleFilterType = 3 +) + +var ( + NpolRuleFilterType_name = map[uint8]string{ + 0: "NPOL_RULE_FILTER_NONE_TYPE", + 1: "NPOL_RULE_FILTER_ICMP_TYPE", + 2: "NPOL_RULE_FILTER_ICMP_CODE", + 3: "NPOL_RULE_FILTER_L4_PROTO", + } + NpolRuleFilterType_value = map[string]uint8{ + "NPOL_RULE_FILTER_NONE_TYPE": 0, + "NPOL_RULE_FILTER_ICMP_TYPE": 1, + "NPOL_RULE_FILTER_ICMP_CODE": 2, + "NPOL_RULE_FILTER_L4_PROTO": 3, + } +) + +func (x NpolRuleFilterType) String() string { + s, ok := NpolRuleFilterType_name[uint8(x)] + if ok { + return s + } + return "NpolRuleFilterType(" + strconv.Itoa(int(x)) + ")" +} + +// NpolEntrySetID defines type 'npol_entry_set_id'. +type NpolEntrySetID struct { + SetID uint32 `binapi:"u32,name=set_id" json:"set_id,omitempty"` +} + +// NpolIpsetMember defines type 'npol_ipset_member'. +type NpolIpsetMember struct { + Val NpolIpsetMemberValUnion `binapi:"npol_ipset_member_val,name=val" json:"val,omitempty"` +} + +// NpolPolicyItem defines type 'npol_policy_item'. +type NpolPolicyItem struct { + IsInbound bool `binapi:"bool,name=is_inbound" json:"is_inbound,omitempty"` + RuleID uint32 `binapi:"u32,name=rule_id" json:"rule_id,omitempty"` +} + +// NpolPortRange defines type 'npol_port_range'. +type NpolPortRange struct { + Start uint16 `binapi:"u16,name=start" json:"start,omitempty"` + End uint16 `binapi:"u16,name=end" json:"end,omitempty"` +} + +// NpolRule defines type 'npol_rule'. +type NpolRule struct { + Action NpolRuleAction `binapi:"npol_rule_action,name=action" json:"action,omitempty"` + Filters [3]NpolRuleFilter `binapi:"npol_rule_filter[3],name=filters" json:"filters,omitempty"` + NumEntries uint32 `binapi:"u32,name=num_entries" json:"-"` + Matches []NpolRuleEntry `binapi:"npol_rule_entry[num_entries],name=matches" json:"matches,omitempty"` +} + +// NpolRuleEntry defines type 'npol_rule_entry'. +type NpolRuleEntry struct { + IsSrc bool `binapi:"bool,name=is_src" json:"is_src,omitempty"` + IsNot bool `binapi:"bool,name=is_not" json:"is_not,omitempty"` + Type NpolEntryType `binapi:"npol_entry_type,name=type" json:"type,omitempty"` + Data NpolEntryDataUnion `binapi:"npol_entry_data,name=data" json:"data,omitempty"` +} + +// NpolRuleFilter defines type 'npol_rule_filter'. +type NpolRuleFilter struct { + Value uint32 `binapi:"u32,name=value" json:"value,omitempty"` + Type NpolRuleFilterType `binapi:"npol_rule_filter_type,name=type" json:"type,omitempty"` + ShouldMatch uint8 `binapi:"u8,name=should_match" json:"should_match,omitempty"` +} + +// NpolThreeTuple defines type 'npol_three_tuple'. +type NpolThreeTuple struct { + Address ip_types.Address `binapi:"address,name=address" json:"address,omitempty"` + L4Proto uint8 `binapi:"u8,name=l4_proto" json:"l4_proto,omitempty"` + Port uint16 `binapi:"u16,name=port" json:"port,omitempty"` +} + +// NpolEntryDataUnion defines union 'npol_entry_data'. +type NpolEntryDataUnion struct { + // NpolEntryDataUnion can be one of: + // - Cidr *ip_types.Prefix + // - PortRange *NpolPortRange + // - SetID *NpolEntrySetID + XXX_UnionData [18]byte +} + +func NpolEntryDataUnionCidr(a ip_types.Prefix) (u NpolEntryDataUnion) { + u.SetCidr(a) + return +} +func (u *NpolEntryDataUnion) SetCidr(a ip_types.Prefix) { + buf := codec.NewBuffer(u.XXX_UnionData[:]) + buf.EncodeUint8(uint8(a.Address.Af)) + buf.EncodeBytes(a.Address.Un.XXX_UnionData[:], 16) + buf.EncodeUint8(a.Len) +} +func (u *NpolEntryDataUnion) GetCidr() (a ip_types.Prefix) { + buf := codec.NewBuffer(u.XXX_UnionData[:]) + a.Address.Af = ip_types.AddressFamily(buf.DecodeUint8()) + copy(a.Address.Un.XXX_UnionData[:], buf.DecodeBytes(16)) + a.Len = buf.DecodeUint8() + return +} + +func NpolEntryDataUnionPortRange(a NpolPortRange) (u NpolEntryDataUnion) { + u.SetPortRange(a) + return +} +func (u *NpolEntryDataUnion) SetPortRange(a NpolPortRange) { + buf := codec.NewBuffer(u.XXX_UnionData[:]) + buf.EncodeUint16(a.Start) + buf.EncodeUint16(a.End) +} +func (u *NpolEntryDataUnion) GetPortRange() (a NpolPortRange) { + buf := codec.NewBuffer(u.XXX_UnionData[:]) + a.Start = buf.DecodeUint16() + a.End = buf.DecodeUint16() + return +} + +func NpolEntryDataUnionSetID(a NpolEntrySetID) (u NpolEntryDataUnion) { + u.SetSetID(a) + return +} +func (u *NpolEntryDataUnion) SetSetID(a NpolEntrySetID) { + buf := codec.NewBuffer(u.XXX_UnionData[:]) + buf.EncodeUint32(a.SetID) +} +func (u *NpolEntryDataUnion) GetSetID() (a NpolEntrySetID) { + buf := codec.NewBuffer(u.XXX_UnionData[:]) + a.SetID = buf.DecodeUint32() + return +} + +// NpolIpsetMemberValUnion defines union 'npol_ipset_member_val'. +type NpolIpsetMemberValUnion struct { + // NpolIpsetMemberValUnion can be one of: + // - Address *ip_types.Address + // - Prefix *ip_types.Prefix + // - Tuple *NpolThreeTuple + XXX_UnionData [20]byte +} + +func NpolIpsetMemberValUnionAddress(a ip_types.Address) (u NpolIpsetMemberValUnion) { + u.SetAddress(a) + return +} +func (u *NpolIpsetMemberValUnion) SetAddress(a ip_types.Address) { + buf := codec.NewBuffer(u.XXX_UnionData[:]) + buf.EncodeUint8(uint8(a.Af)) + buf.EncodeBytes(a.Un.XXX_UnionData[:], 16) +} +func (u *NpolIpsetMemberValUnion) GetAddress() (a ip_types.Address) { + buf := codec.NewBuffer(u.XXX_UnionData[:]) + a.Af = ip_types.AddressFamily(buf.DecodeUint8()) + copy(a.Un.XXX_UnionData[:], buf.DecodeBytes(16)) + return +} + +func NpolIpsetMemberValUnionPrefix(a ip_types.Prefix) (u NpolIpsetMemberValUnion) { + u.SetPrefix(a) + return +} +func (u *NpolIpsetMemberValUnion) SetPrefix(a ip_types.Prefix) { + buf := codec.NewBuffer(u.XXX_UnionData[:]) + buf.EncodeUint8(uint8(a.Address.Af)) + buf.EncodeBytes(a.Address.Un.XXX_UnionData[:], 16) + buf.EncodeUint8(a.Len) +} +func (u *NpolIpsetMemberValUnion) GetPrefix() (a ip_types.Prefix) { + buf := codec.NewBuffer(u.XXX_UnionData[:]) + a.Address.Af = ip_types.AddressFamily(buf.DecodeUint8()) + copy(a.Address.Un.XXX_UnionData[:], buf.DecodeBytes(16)) + a.Len = buf.DecodeUint8() + return +} + +func NpolIpsetMemberValUnionTuple(a NpolThreeTuple) (u NpolIpsetMemberValUnion) { + u.SetTuple(a) + return +} +func (u *NpolIpsetMemberValUnion) SetTuple(a NpolThreeTuple) { + buf := codec.NewBuffer(u.XXX_UnionData[:]) + buf.EncodeUint8(uint8(a.Address.Af)) + buf.EncodeBytes(a.Address.Un.XXX_UnionData[:], 16) + buf.EncodeUint8(a.L4Proto) + buf.EncodeUint16(a.Port) +} +func (u *NpolIpsetMemberValUnion) GetTuple() (a NpolThreeTuple) { + buf := codec.NewBuffer(u.XXX_UnionData[:]) + a.Address.Af = ip_types.AddressFamily(buf.DecodeUint8()) + copy(a.Address.Un.XXX_UnionData[:], buf.DecodeBytes(16)) + a.L4Proto = buf.DecodeUint8() + a.Port = buf.DecodeUint16() + return +} + +// NpolConfigurePolicies defines message 'npol_configure_policies'. +type NpolConfigurePolicies struct { + SwIfIndex uint32 `binapi:"u32,name=sw_if_index" json:"sw_if_index,omitempty"` + NumRxPolicies uint32 `binapi:"u32,name=num_rx_policies" json:"num_rx_policies,omitempty"` + NumTxPolicies uint32 `binapi:"u32,name=num_tx_policies" json:"num_tx_policies,omitempty"` + TotalIds uint32 `binapi:"u32,name=total_ids" json:"-"` + InvertRxTx uint8 `binapi:"u8,name=invert_rx_tx" json:"invert_rx_tx,omitempty"` + PolicyDefaultRx NpolPolicyDefault `binapi:"npol_policy_default,name=policy_default_rx" json:"policy_default_rx,omitempty"` + PolicyDefaultTx NpolPolicyDefault `binapi:"npol_policy_default,name=policy_default_tx" json:"policy_default_tx,omitempty"` + ProfileDefaultRx NpolPolicyDefault `binapi:"npol_policy_default,name=profile_default_rx" json:"profile_default_rx,omitempty"` + ProfileDefaultTx NpolPolicyDefault `binapi:"npol_policy_default,name=profile_default_tx" json:"profile_default_tx,omitempty"` + PolicyIds []uint32 `binapi:"u32[total_ids],name=policy_ids" json:"policy_ids,omitempty"` +} + +func (m *NpolConfigurePolicies) Reset() { *m = NpolConfigurePolicies{} } +func (*NpolConfigurePolicies) GetMessageName() string { return "npol_configure_policies" } +func (*NpolConfigurePolicies) GetCrcString() string { return "66fe1335" } +func (*NpolConfigurePolicies) GetMessageType() api.MessageType { + return api.RequestMessage +} + +func (m *NpolConfigurePolicies) Size() (size int) { + if m == nil { + return 0 + } + size += 4 // m.SwIfIndex + size += 4 // m.NumRxPolicies + size += 4 // m.NumTxPolicies + size += 4 // m.TotalIds + size += 1 // m.InvertRxTx + size += 1 // m.PolicyDefaultRx + size += 1 // m.PolicyDefaultTx + size += 1 // m.ProfileDefaultRx + size += 1 // m.ProfileDefaultTx + size += 4 * len(m.PolicyIds) // m.PolicyIds + return size +} +func (m *NpolConfigurePolicies) Marshal(b []byte) ([]byte, error) { + if b == nil { + b = make([]byte, m.Size()) + } + buf := codec.NewBuffer(b) + buf.EncodeUint32(m.SwIfIndex) + buf.EncodeUint32(m.NumRxPolicies) + buf.EncodeUint32(m.NumTxPolicies) + buf.EncodeUint32(uint32(len(m.PolicyIds))) + buf.EncodeUint8(m.InvertRxTx) + buf.EncodeUint8(uint8(m.PolicyDefaultRx)) + buf.EncodeUint8(uint8(m.PolicyDefaultTx)) + buf.EncodeUint8(uint8(m.ProfileDefaultRx)) + buf.EncodeUint8(uint8(m.ProfileDefaultTx)) + for i := 0; i < len(m.PolicyIds); i++ { + var x uint32 + if i < len(m.PolicyIds) { + x = uint32(m.PolicyIds[i]) + } + buf.EncodeUint32(x) + } + return buf.Bytes(), nil +} +func (m *NpolConfigurePolicies) Unmarshal(b []byte) error { + buf := codec.NewBuffer(b) + m.SwIfIndex = buf.DecodeUint32() + m.NumRxPolicies = buf.DecodeUint32() + m.NumTxPolicies = buf.DecodeUint32() + m.TotalIds = buf.DecodeUint32() + m.InvertRxTx = buf.DecodeUint8() + m.PolicyDefaultRx = NpolPolicyDefault(buf.DecodeUint8()) + m.PolicyDefaultTx = NpolPolicyDefault(buf.DecodeUint8()) + m.ProfileDefaultRx = NpolPolicyDefault(buf.DecodeUint8()) + m.ProfileDefaultTx = NpolPolicyDefault(buf.DecodeUint8()) + m.PolicyIds = make([]uint32, m.TotalIds) + for i := 0; i < len(m.PolicyIds); i++ { + m.PolicyIds[i] = buf.DecodeUint32() + } + return nil +} + +// NpolConfigurePoliciesReply defines message 'npol_configure_policies_reply'. +type NpolConfigurePoliciesReply struct { + Retval int32 `binapi:"i32,name=retval" json:"retval,omitempty"` +} + +func (m *NpolConfigurePoliciesReply) Reset() { *m = NpolConfigurePoliciesReply{} } +func (*NpolConfigurePoliciesReply) GetMessageName() string { return "npol_configure_policies_reply" } +func (*NpolConfigurePoliciesReply) GetCrcString() string { return "e8d4e804" } +func (*NpolConfigurePoliciesReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} + +func (m *NpolConfigurePoliciesReply) Size() (size int) { + if m == nil { + return 0 + } + size += 4 // m.Retval + return size +} +func (m *NpolConfigurePoliciesReply) Marshal(b []byte) ([]byte, error) { + if b == nil { + b = make([]byte, m.Size()) + } + buf := codec.NewBuffer(b) + buf.EncodeInt32(m.Retval) + return buf.Bytes(), nil +} +func (m *NpolConfigurePoliciesReply) Unmarshal(b []byte) error { + buf := codec.NewBuffer(b) + m.Retval = buf.DecodeInt32() + return nil +} + +// Get the plugin version +// NpolGetVersion defines message 'npol_get_version'. +type NpolGetVersion struct{} + +func (m *NpolGetVersion) Reset() { *m = NpolGetVersion{} } +func (*NpolGetVersion) GetMessageName() string { return "npol_get_version" } +func (*NpolGetVersion) GetCrcString() string { return "51077d14" } +func (*NpolGetVersion) GetMessageType() api.MessageType { + return api.RequestMessage +} + +func (m *NpolGetVersion) Size() (size int) { + if m == nil { + return 0 + } + return size +} +func (m *NpolGetVersion) Marshal(b []byte) ([]byte, error) { + if b == nil { + b = make([]byte, m.Size()) + } + buf := codec.NewBuffer(b) + return buf.Bytes(), nil +} +func (m *NpolGetVersion) Unmarshal(b []byte) error { + return nil +} + +// Reply to get the plugin version +// - major - Incremented every time a known breaking behavior change is introduced +// - minor - Incremented with small changes, may be used to avoid buggy versions +// +// NpolGetVersionReply defines message 'npol_get_version_reply'. +type NpolGetVersionReply struct { + Major uint32 `binapi:"u32,name=major" json:"major,omitempty"` + Minor uint32 `binapi:"u32,name=minor" json:"minor,omitempty"` +} + +func (m *NpolGetVersionReply) Reset() { *m = NpolGetVersionReply{} } +func (*NpolGetVersionReply) GetMessageName() string { return "npol_get_version_reply" } +func (*NpolGetVersionReply) GetCrcString() string { return "9b32cf86" } +func (*NpolGetVersionReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} + +func (m *NpolGetVersionReply) Size() (size int) { + if m == nil { + return 0 + } + size += 4 // m.Major + size += 4 // m.Minor + return size +} +func (m *NpolGetVersionReply) Marshal(b []byte) ([]byte, error) { + if b == nil { + b = make([]byte, m.Size()) + } + buf := codec.NewBuffer(b) + buf.EncodeUint32(m.Major) + buf.EncodeUint32(m.Minor) + return buf.Bytes(), nil +} +func (m *NpolGetVersionReply) Unmarshal(b []byte) error { + buf := codec.NewBuffer(b) + m.Major = buf.DecodeUint32() + m.Minor = buf.DecodeUint32() + return nil +} + +// NpolIpsetAddDelMembers defines message 'npol_ipset_add_del_members'. +type NpolIpsetAddDelMembers struct { + SetID uint32 `binapi:"u32,name=set_id" json:"set_id,omitempty"` + IsAdd bool `binapi:"bool,name=is_add" json:"is_add,omitempty"` + Len uint32 `binapi:"u32,name=len" json:"-"` + Members []NpolIpsetMember `binapi:"npol_ipset_member[len],name=members" json:"members,omitempty"` +} + +func (m *NpolIpsetAddDelMembers) Reset() { *m = NpolIpsetAddDelMembers{} } +func (*NpolIpsetAddDelMembers) GetMessageName() string { return "npol_ipset_add_del_members" } +func (*NpolIpsetAddDelMembers) GetCrcString() string { return "8ad1b2ed" } +func (*NpolIpsetAddDelMembers) GetMessageType() api.MessageType { + return api.RequestMessage +} + +func (m *NpolIpsetAddDelMembers) Size() (size int) { + if m == nil { + return 0 + } + size += 4 // m.SetID + size += 1 // m.IsAdd + size += 4 // m.Len + for j1 := 0; j1 < len(m.Members); j1++ { + var s1 NpolIpsetMember + _ = s1 + if j1 < len(m.Members) { + s1 = m.Members[j1] + } + size += 1 * 20 // s1.Val + } + return size +} +func (m *NpolIpsetAddDelMembers) Marshal(b []byte) ([]byte, error) { + if b == nil { + b = make([]byte, m.Size()) + } + buf := codec.NewBuffer(b) + buf.EncodeUint32(m.SetID) + buf.EncodeBool(m.IsAdd) + buf.EncodeUint32(uint32(len(m.Members))) + for j0 := 0; j0 < len(m.Members); j0++ { + var v0 NpolIpsetMember // Members + if j0 < len(m.Members) { + v0 = m.Members[j0] + } + buf.EncodeBytes(v0.Val.XXX_UnionData[:], 20) + } + return buf.Bytes(), nil +} +func (m *NpolIpsetAddDelMembers) Unmarshal(b []byte) error { + buf := codec.NewBuffer(b) + m.SetID = buf.DecodeUint32() + m.IsAdd = buf.DecodeBool() + m.Len = buf.DecodeUint32() + m.Members = make([]NpolIpsetMember, m.Len) + for j0 := 0; j0 < len(m.Members); j0++ { + copy(m.Members[j0].Val.XXX_UnionData[:], buf.DecodeBytes(20)) + } + return nil +} + +// NpolIpsetAddDelMembersReply defines message 'npol_ipset_add_del_members_reply'. +type NpolIpsetAddDelMembersReply struct { + Retval int32 `binapi:"i32,name=retval" json:"retval,omitempty"` +} + +func (m *NpolIpsetAddDelMembersReply) Reset() { *m = NpolIpsetAddDelMembersReply{} } +func (*NpolIpsetAddDelMembersReply) GetMessageName() string { + return "npol_ipset_add_del_members_reply" +} +func (*NpolIpsetAddDelMembersReply) GetCrcString() string { return "e8d4e804" } +func (*NpolIpsetAddDelMembersReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} + +func (m *NpolIpsetAddDelMembersReply) Size() (size int) { + if m == nil { + return 0 + } + size += 4 // m.Retval + return size +} +func (m *NpolIpsetAddDelMembersReply) Marshal(b []byte) ([]byte, error) { + if b == nil { + b = make([]byte, m.Size()) + } + buf := codec.NewBuffer(b) + buf.EncodeInt32(m.Retval) + return buf.Bytes(), nil +} +func (m *NpolIpsetAddDelMembersReply) Unmarshal(b []byte) error { + buf := codec.NewBuffer(b) + m.Retval = buf.DecodeInt32() + return nil +} + +// NpolIpsetCreate defines message 'npol_ipset_create'. +type NpolIpsetCreate struct { + Type NpolIpsetType `binapi:"npol_ipset_type,name=type" json:"type,omitempty"` +} + +func (m *NpolIpsetCreate) Reset() { *m = NpolIpsetCreate{} } +func (*NpolIpsetCreate) GetMessageName() string { return "npol_ipset_create" } +func (*NpolIpsetCreate) GetCrcString() string { return "f948b404" } +func (*NpolIpsetCreate) GetMessageType() api.MessageType { + return api.RequestMessage +} + +func (m *NpolIpsetCreate) Size() (size int) { + if m == nil { + return 0 + } + size += 1 // m.Type + return size +} +func (m *NpolIpsetCreate) Marshal(b []byte) ([]byte, error) { + if b == nil { + b = make([]byte, m.Size()) + } + buf := codec.NewBuffer(b) + buf.EncodeUint8(uint8(m.Type)) + return buf.Bytes(), nil +} +func (m *NpolIpsetCreate) Unmarshal(b []byte) error { + buf := codec.NewBuffer(b) + m.Type = NpolIpsetType(buf.DecodeUint8()) + return nil +} + +// NpolIpsetCreateReply defines message 'npol_ipset_create_reply'. +type NpolIpsetCreateReply struct { + Retval int32 `binapi:"i32,name=retval" json:"retval,omitempty"` + SetID uint32 `binapi:"u32,name=set_id" json:"set_id,omitempty"` +} + +func (m *NpolIpsetCreateReply) Reset() { *m = NpolIpsetCreateReply{} } +func (*NpolIpsetCreateReply) GetMessageName() string { return "npol_ipset_create_reply" } +func (*NpolIpsetCreateReply) GetCrcString() string { return "6a43f193" } +func (*NpolIpsetCreateReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} + +func (m *NpolIpsetCreateReply) Size() (size int) { + if m == nil { + return 0 + } + size += 4 // m.Retval + size += 4 // m.SetID + return size +} +func (m *NpolIpsetCreateReply) Marshal(b []byte) ([]byte, error) { + if b == nil { + b = make([]byte, m.Size()) + } + buf := codec.NewBuffer(b) + buf.EncodeInt32(m.Retval) + buf.EncodeUint32(m.SetID) + return buf.Bytes(), nil +} +func (m *NpolIpsetCreateReply) Unmarshal(b []byte) error { + buf := codec.NewBuffer(b) + m.Retval = buf.DecodeInt32() + m.SetID = buf.DecodeUint32() + return nil +} + +// NpolIpsetDelete defines message 'npol_ipset_delete'. +type NpolIpsetDelete struct { + SetID uint32 `binapi:"u32,name=set_id" json:"set_id,omitempty"` +} + +func (m *NpolIpsetDelete) Reset() { *m = NpolIpsetDelete{} } +func (*NpolIpsetDelete) GetMessageName() string { return "npol_ipset_delete" } +func (*NpolIpsetDelete) GetCrcString() string { return "ceacdbcb" } +func (*NpolIpsetDelete) GetMessageType() api.MessageType { + return api.RequestMessage +} + +func (m *NpolIpsetDelete) Size() (size int) { + if m == nil { + return 0 + } + size += 4 // m.SetID + return size +} +func (m *NpolIpsetDelete) Marshal(b []byte) ([]byte, error) { + if b == nil { + b = make([]byte, m.Size()) + } + buf := codec.NewBuffer(b) + buf.EncodeUint32(m.SetID) + return buf.Bytes(), nil +} +func (m *NpolIpsetDelete) Unmarshal(b []byte) error { + buf := codec.NewBuffer(b) + m.SetID = buf.DecodeUint32() + return nil +} + +// NpolIpsetDeleteReply defines message 'npol_ipset_delete_reply'. +type NpolIpsetDeleteReply struct { + Retval int32 `binapi:"i32,name=retval" json:"retval,omitempty"` +} + +func (m *NpolIpsetDeleteReply) Reset() { *m = NpolIpsetDeleteReply{} } +func (*NpolIpsetDeleteReply) GetMessageName() string { return "npol_ipset_delete_reply" } +func (*NpolIpsetDeleteReply) GetCrcString() string { return "e8d4e804" } +func (*NpolIpsetDeleteReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} + +func (m *NpolIpsetDeleteReply) Size() (size int) { + if m == nil { + return 0 + } + size += 4 // m.Retval + return size +} +func (m *NpolIpsetDeleteReply) Marshal(b []byte) ([]byte, error) { + if b == nil { + b = make([]byte, m.Size()) + } + buf := codec.NewBuffer(b) + buf.EncodeInt32(m.Retval) + return buf.Bytes(), nil +} +func (m *NpolIpsetDeleteReply) Unmarshal(b []byte) error { + buf := codec.NewBuffer(b) + m.Retval = buf.DecodeInt32() + return nil +} + +// NpolPolicyCreate defines message 'npol_policy_create'. +type NpolPolicyCreate struct { + NumItems uint32 `binapi:"u32,name=num_items" json:"-"` + Rules []NpolPolicyItem `binapi:"npol_policy_item[num_items],name=rules" json:"rules,omitempty"` +} + +func (m *NpolPolicyCreate) Reset() { *m = NpolPolicyCreate{} } +func (*NpolPolicyCreate) GetMessageName() string { return "npol_policy_create" } +func (*NpolPolicyCreate) GetCrcString() string { return "3441bb97" } +func (*NpolPolicyCreate) GetMessageType() api.MessageType { + return api.RequestMessage +} + +func (m *NpolPolicyCreate) Size() (size int) { + if m == nil { + return 0 + } + size += 4 // m.NumItems + for j1 := 0; j1 < len(m.Rules); j1++ { + var s1 NpolPolicyItem + _ = s1 + if j1 < len(m.Rules) { + s1 = m.Rules[j1] + } + size += 1 // s1.IsInbound + size += 4 // s1.RuleID + } + return size +} +func (m *NpolPolicyCreate) Marshal(b []byte) ([]byte, error) { + if b == nil { + b = make([]byte, m.Size()) + } + buf := codec.NewBuffer(b) + buf.EncodeUint32(uint32(len(m.Rules))) + for j0 := 0; j0 < len(m.Rules); j0++ { + var v0 NpolPolicyItem // Rules + if j0 < len(m.Rules) { + v0 = m.Rules[j0] + } + buf.EncodeBool(v0.IsInbound) + buf.EncodeUint32(v0.RuleID) + } + return buf.Bytes(), nil +} +func (m *NpolPolicyCreate) Unmarshal(b []byte) error { + buf := codec.NewBuffer(b) + m.NumItems = buf.DecodeUint32() + m.Rules = make([]NpolPolicyItem, m.NumItems) + for j0 := 0; j0 < len(m.Rules); j0++ { + m.Rules[j0].IsInbound = buf.DecodeBool() + m.Rules[j0].RuleID = buf.DecodeUint32() + } + return nil +} + +// NpolPolicyCreateReply defines message 'npol_policy_create_reply'. +type NpolPolicyCreateReply struct { + Retval int32 `binapi:"i32,name=retval" json:"retval,omitempty"` + PolicyID uint32 `binapi:"u32,name=policy_id" json:"policy_id,omitempty"` +} + +func (m *NpolPolicyCreateReply) Reset() { *m = NpolPolicyCreateReply{} } +func (*NpolPolicyCreateReply) GetMessageName() string { return "npol_policy_create_reply" } +func (*NpolPolicyCreateReply) GetCrcString() string { return "90f27405" } +func (*NpolPolicyCreateReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} + +func (m *NpolPolicyCreateReply) Size() (size int) { + if m == nil { + return 0 + } + size += 4 // m.Retval + size += 4 // m.PolicyID + return size +} +func (m *NpolPolicyCreateReply) Marshal(b []byte) ([]byte, error) { + if b == nil { + b = make([]byte, m.Size()) + } + buf := codec.NewBuffer(b) + buf.EncodeInt32(m.Retval) + buf.EncodeUint32(m.PolicyID) + return buf.Bytes(), nil +} +func (m *NpolPolicyCreateReply) Unmarshal(b []byte) error { + buf := codec.NewBuffer(b) + m.Retval = buf.DecodeInt32() + m.PolicyID = buf.DecodeUint32() + return nil +} + +// NpolPolicyDelete defines message 'npol_policy_delete'. +type NpolPolicyDelete struct { + PolicyID uint32 `binapi:"u32,name=policy_id" json:"policy_id,omitempty"` +} + +func (m *NpolPolicyDelete) Reset() { *m = NpolPolicyDelete{} } +func (*NpolPolicyDelete) GetMessageName() string { return "npol_policy_delete" } +func (*NpolPolicyDelete) GetCrcString() string { return "ad833868" } +func (*NpolPolicyDelete) GetMessageType() api.MessageType { + return api.RequestMessage +} + +func (m *NpolPolicyDelete) Size() (size int) { + if m == nil { + return 0 + } + size += 4 // m.PolicyID + return size +} +func (m *NpolPolicyDelete) Marshal(b []byte) ([]byte, error) { + if b == nil { + b = make([]byte, m.Size()) + } + buf := codec.NewBuffer(b) + buf.EncodeUint32(m.PolicyID) + return buf.Bytes(), nil +} +func (m *NpolPolicyDelete) Unmarshal(b []byte) error { + buf := codec.NewBuffer(b) + m.PolicyID = buf.DecodeUint32() + return nil +} + +// NpolPolicyDeleteReply defines message 'npol_policy_delete_reply'. +type NpolPolicyDeleteReply struct { + Retval int32 `binapi:"i32,name=retval" json:"retval,omitempty"` +} + +func (m *NpolPolicyDeleteReply) Reset() { *m = NpolPolicyDeleteReply{} } +func (*NpolPolicyDeleteReply) GetMessageName() string { return "npol_policy_delete_reply" } +func (*NpolPolicyDeleteReply) GetCrcString() string { return "e8d4e804" } +func (*NpolPolicyDeleteReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} + +func (m *NpolPolicyDeleteReply) Size() (size int) { + if m == nil { + return 0 + } + size += 4 // m.Retval + return size +} +func (m *NpolPolicyDeleteReply) Marshal(b []byte) ([]byte, error) { + if b == nil { + b = make([]byte, m.Size()) + } + buf := codec.NewBuffer(b) + buf.EncodeInt32(m.Retval) + return buf.Bytes(), nil +} +func (m *NpolPolicyDeleteReply) Unmarshal(b []byte) error { + buf := codec.NewBuffer(b) + m.Retval = buf.DecodeInt32() + return nil +} + +// NpolPolicyUpdate defines message 'npol_policy_update'. +type NpolPolicyUpdate struct { + PolicyID uint32 `binapi:"u32,name=policy_id" json:"policy_id,omitempty"` + NumItems uint32 `binapi:"u32,name=num_items" json:"-"` + Rules []NpolPolicyItem `binapi:"npol_policy_item[num_items],name=rules" json:"rules,omitempty"` +} + +func (m *NpolPolicyUpdate) Reset() { *m = NpolPolicyUpdate{} } +func (*NpolPolicyUpdate) GetMessageName() string { return "npol_policy_update" } +func (*NpolPolicyUpdate) GetCrcString() string { return "21a5f7ef" } +func (*NpolPolicyUpdate) GetMessageType() api.MessageType { + return api.RequestMessage +} + +func (m *NpolPolicyUpdate) Size() (size int) { + if m == nil { + return 0 + } + size += 4 // m.PolicyID + size += 4 // m.NumItems + for j1 := 0; j1 < len(m.Rules); j1++ { + var s1 NpolPolicyItem + _ = s1 + if j1 < len(m.Rules) { + s1 = m.Rules[j1] + } + size += 1 // s1.IsInbound + size += 4 // s1.RuleID + } + return size +} +func (m *NpolPolicyUpdate) Marshal(b []byte) ([]byte, error) { + if b == nil { + b = make([]byte, m.Size()) + } + buf := codec.NewBuffer(b) + buf.EncodeUint32(m.PolicyID) + buf.EncodeUint32(uint32(len(m.Rules))) + for j0 := 0; j0 < len(m.Rules); j0++ { + var v0 NpolPolicyItem // Rules + if j0 < len(m.Rules) { + v0 = m.Rules[j0] + } + buf.EncodeBool(v0.IsInbound) + buf.EncodeUint32(v0.RuleID) + } + return buf.Bytes(), nil +} +func (m *NpolPolicyUpdate) Unmarshal(b []byte) error { + buf := codec.NewBuffer(b) + m.PolicyID = buf.DecodeUint32() + m.NumItems = buf.DecodeUint32() + m.Rules = make([]NpolPolicyItem, m.NumItems) + for j0 := 0; j0 < len(m.Rules); j0++ { + m.Rules[j0].IsInbound = buf.DecodeBool() + m.Rules[j0].RuleID = buf.DecodeUint32() + } + return nil +} + +// NpolPolicyUpdateReply defines message 'npol_policy_update_reply'. +type NpolPolicyUpdateReply struct { + Retval int32 `binapi:"i32,name=retval" json:"retval,omitempty"` +} + +func (m *NpolPolicyUpdateReply) Reset() { *m = NpolPolicyUpdateReply{} } +func (*NpolPolicyUpdateReply) GetMessageName() string { return "npol_policy_update_reply" } +func (*NpolPolicyUpdateReply) GetCrcString() string { return "e8d4e804" } +func (*NpolPolicyUpdateReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} + +func (m *NpolPolicyUpdateReply) Size() (size int) { + if m == nil { + return 0 + } + size += 4 // m.Retval + return size +} +func (m *NpolPolicyUpdateReply) Marshal(b []byte) ([]byte, error) { + if b == nil { + b = make([]byte, m.Size()) + } + buf := codec.NewBuffer(b) + buf.EncodeInt32(m.Retval) + return buf.Bytes(), nil +} +func (m *NpolPolicyUpdateReply) Unmarshal(b []byte) error { + buf := codec.NewBuffer(b) + m.Retval = buf.DecodeInt32() + return nil +} + +// // where the packet only needs to match one entry in either category +// NpolRuleCreate defines message 'npol_rule_create'. +type NpolRuleCreate struct { + Rule NpolRule `binapi:"npol_rule,name=rule" json:"rule,omitempty"` +} + +func (m *NpolRuleCreate) Reset() { *m = NpolRuleCreate{} } +func (*NpolRuleCreate) GetMessageName() string { return "npol_rule_create" } +func (*NpolRuleCreate) GetCrcString() string { return "f113de45" } +func (*NpolRuleCreate) GetMessageType() api.MessageType { + return api.RequestMessage +} + +func (m *NpolRuleCreate) Size() (size int) { + if m == nil { + return 0 + } + size += 1 // m.Rule.Action + for j2 := 0; j2 < 3; j2++ { + size += 4 // m.Rule.Filters[j2].Value + size += 1 // m.Rule.Filters[j2].Type + size += 1 // m.Rule.Filters[j2].ShouldMatch + } + size += 4 // m.Rule.NumEntries + for j2 := 0; j2 < len(m.Rule.Matches); j2++ { + var s2 NpolRuleEntry + _ = s2 + if j2 < len(m.Rule.Matches) { + s2 = m.Rule.Matches[j2] + } + size += 1 // s2.IsSrc + size += 1 // s2.IsNot + size += 1 // s2.Type + size += 1 * 18 // s2.Data + } + return size +} +func (m *NpolRuleCreate) Marshal(b []byte) ([]byte, error) { + if b == nil { + b = make([]byte, m.Size()) + } + buf := codec.NewBuffer(b) + buf.EncodeUint8(uint8(m.Rule.Action)) + for j1 := 0; j1 < 3; j1++ { + buf.EncodeUint32(m.Rule.Filters[j1].Value) + buf.EncodeUint8(uint8(m.Rule.Filters[j1].Type)) + buf.EncodeUint8(m.Rule.Filters[j1].ShouldMatch) + } + buf.EncodeUint32(uint32(len(m.Rule.Matches))) + for j1 := 0; j1 < len(m.Rule.Matches); j1++ { + var v1 NpolRuleEntry // Matches + if j1 < len(m.Rule.Matches) { + v1 = m.Rule.Matches[j1] + } + buf.EncodeBool(v1.IsSrc) + buf.EncodeBool(v1.IsNot) + buf.EncodeUint8(uint8(v1.Type)) + buf.EncodeBytes(v1.Data.XXX_UnionData[:], 18) + } + return buf.Bytes(), nil +} +func (m *NpolRuleCreate) Unmarshal(b []byte) error { + buf := codec.NewBuffer(b) + m.Rule.Action = NpolRuleAction(buf.DecodeUint8()) + for j1 := 0; j1 < 3; j1++ { + m.Rule.Filters[j1].Value = buf.DecodeUint32() + m.Rule.Filters[j1].Type = NpolRuleFilterType(buf.DecodeUint8()) + m.Rule.Filters[j1].ShouldMatch = buf.DecodeUint8() + } + m.Rule.NumEntries = buf.DecodeUint32() + m.Rule.Matches = make([]NpolRuleEntry, m.Rule.NumEntries) + for j1 := 0; j1 < len(m.Rule.Matches); j1++ { + m.Rule.Matches[j1].IsSrc = buf.DecodeBool() + m.Rule.Matches[j1].IsNot = buf.DecodeBool() + m.Rule.Matches[j1].Type = NpolEntryType(buf.DecodeUint8()) + copy(m.Rule.Matches[j1].Data.XXX_UnionData[:], buf.DecodeBytes(18)) + } + return nil +} + +// NpolRuleCreateReply defines message 'npol_rule_create_reply'. +type NpolRuleCreateReply struct { + Retval int32 `binapi:"i32,name=retval" json:"retval,omitempty"` + RuleID uint32 `binapi:"u32,name=rule_id" json:"rule_id,omitempty"` +} + +func (m *NpolRuleCreateReply) Reset() { *m = NpolRuleCreateReply{} } +func (*NpolRuleCreateReply) GetMessageName() string { return "npol_rule_create_reply" } +func (*NpolRuleCreateReply) GetCrcString() string { return "b48f8052" } +func (*NpolRuleCreateReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} + +func (m *NpolRuleCreateReply) Size() (size int) { + if m == nil { + return 0 + } + size += 4 // m.Retval + size += 4 // m.RuleID + return size +} +func (m *NpolRuleCreateReply) Marshal(b []byte) ([]byte, error) { + if b == nil { + b = make([]byte, m.Size()) + } + buf := codec.NewBuffer(b) + buf.EncodeInt32(m.Retval) + buf.EncodeUint32(m.RuleID) + return buf.Bytes(), nil +} +func (m *NpolRuleCreateReply) Unmarshal(b []byte) error { + buf := codec.NewBuffer(b) + m.Retval = buf.DecodeInt32() + m.RuleID = buf.DecodeUint32() + return nil +} + +// NpolRuleDelete defines message 'npol_rule_delete'. +type NpolRuleDelete struct { + RuleID uint32 `binapi:"u32,name=rule_id" json:"rule_id,omitempty"` +} + +func (m *NpolRuleDelete) Reset() { *m = NpolRuleDelete{} } +func (*NpolRuleDelete) GetMessageName() string { return "npol_rule_delete" } +func (*NpolRuleDelete) GetCrcString() string { return "d19bb6be" } +func (*NpolRuleDelete) GetMessageType() api.MessageType { + return api.RequestMessage +} + +func (m *NpolRuleDelete) Size() (size int) { + if m == nil { + return 0 + } + size += 4 // m.RuleID + return size +} +func (m *NpolRuleDelete) Marshal(b []byte) ([]byte, error) { + if b == nil { + b = make([]byte, m.Size()) + } + buf := codec.NewBuffer(b) + buf.EncodeUint32(m.RuleID) + return buf.Bytes(), nil +} +func (m *NpolRuleDelete) Unmarshal(b []byte) error { + buf := codec.NewBuffer(b) + m.RuleID = buf.DecodeUint32() + return nil +} + +// NpolRuleDeleteReply defines message 'npol_rule_delete_reply'. +type NpolRuleDeleteReply struct { + Retval int32 `binapi:"i32,name=retval" json:"retval,omitempty"` +} + +func (m *NpolRuleDeleteReply) Reset() { *m = NpolRuleDeleteReply{} } +func (*NpolRuleDeleteReply) GetMessageName() string { return "npol_rule_delete_reply" } +func (*NpolRuleDeleteReply) GetCrcString() string { return "e8d4e804" } +func (*NpolRuleDeleteReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} + +func (m *NpolRuleDeleteReply) Size() (size int) { + if m == nil { + return 0 + } + size += 4 // m.Retval + return size +} +func (m *NpolRuleDeleteReply) Marshal(b []byte) ([]byte, error) { + if b == nil { + b = make([]byte, m.Size()) + } + buf := codec.NewBuffer(b) + buf.EncodeInt32(m.Retval) + return buf.Bytes(), nil +} +func (m *NpolRuleDeleteReply) Unmarshal(b []byte) error { + buf := codec.NewBuffer(b) + m.Retval = buf.DecodeInt32() + return nil +} + +// NpolRuleUpdate defines message 'npol_rule_update'. +type NpolRuleUpdate struct { + RuleID uint32 `binapi:"u32,name=rule_id" json:"rule_id,omitempty"` + Rule NpolRule `binapi:"npol_rule,name=rule" json:"rule,omitempty"` +} + +func (m *NpolRuleUpdate) Reset() { *m = NpolRuleUpdate{} } +func (*NpolRuleUpdate) GetMessageName() string { return "npol_rule_update" } +func (*NpolRuleUpdate) GetCrcString() string { return "e38bffe2" } +func (*NpolRuleUpdate) GetMessageType() api.MessageType { + return api.RequestMessage +} + +func (m *NpolRuleUpdate) Size() (size int) { + if m == nil { + return 0 + } + size += 4 // m.RuleID + size += 1 // m.Rule.Action + for j2 := 0; j2 < 3; j2++ { + size += 4 // m.Rule.Filters[j2].Value + size += 1 // m.Rule.Filters[j2].Type + size += 1 // m.Rule.Filters[j2].ShouldMatch + } + size += 4 // m.Rule.NumEntries + for j2 := 0; j2 < len(m.Rule.Matches); j2++ { + var s2 NpolRuleEntry + _ = s2 + if j2 < len(m.Rule.Matches) { + s2 = m.Rule.Matches[j2] + } + size += 1 // s2.IsSrc + size += 1 // s2.IsNot + size += 1 // s2.Type + size += 1 * 18 // s2.Data + } + return size +} +func (m *NpolRuleUpdate) Marshal(b []byte) ([]byte, error) { + if b == nil { + b = make([]byte, m.Size()) + } + buf := codec.NewBuffer(b) + buf.EncodeUint32(m.RuleID) + buf.EncodeUint8(uint8(m.Rule.Action)) + for j1 := 0; j1 < 3; j1++ { + buf.EncodeUint32(m.Rule.Filters[j1].Value) + buf.EncodeUint8(uint8(m.Rule.Filters[j1].Type)) + buf.EncodeUint8(m.Rule.Filters[j1].ShouldMatch) + } + buf.EncodeUint32(uint32(len(m.Rule.Matches))) + for j1 := 0; j1 < len(m.Rule.Matches); j1++ { + var v1 NpolRuleEntry // Matches + if j1 < len(m.Rule.Matches) { + v1 = m.Rule.Matches[j1] + } + buf.EncodeBool(v1.IsSrc) + buf.EncodeBool(v1.IsNot) + buf.EncodeUint8(uint8(v1.Type)) + buf.EncodeBytes(v1.Data.XXX_UnionData[:], 18) + } + return buf.Bytes(), nil +} +func (m *NpolRuleUpdate) Unmarshal(b []byte) error { + buf := codec.NewBuffer(b) + m.RuleID = buf.DecodeUint32() + m.Rule.Action = NpolRuleAction(buf.DecodeUint8()) + for j1 := 0; j1 < 3; j1++ { + m.Rule.Filters[j1].Value = buf.DecodeUint32() + m.Rule.Filters[j1].Type = NpolRuleFilterType(buf.DecodeUint8()) + m.Rule.Filters[j1].ShouldMatch = buf.DecodeUint8() + } + m.Rule.NumEntries = buf.DecodeUint32() + m.Rule.Matches = make([]NpolRuleEntry, m.Rule.NumEntries) + for j1 := 0; j1 < len(m.Rule.Matches); j1++ { + m.Rule.Matches[j1].IsSrc = buf.DecodeBool() + m.Rule.Matches[j1].IsNot = buf.DecodeBool() + m.Rule.Matches[j1].Type = NpolEntryType(buf.DecodeUint8()) + copy(m.Rule.Matches[j1].Data.XXX_UnionData[:], buf.DecodeBytes(18)) + } + return nil +} + +// NpolRuleUpdateReply defines message 'npol_rule_update_reply'. +type NpolRuleUpdateReply struct { + Retval int32 `binapi:"i32,name=retval" json:"retval,omitempty"` +} + +func (m *NpolRuleUpdateReply) Reset() { *m = NpolRuleUpdateReply{} } +func (*NpolRuleUpdateReply) GetMessageName() string { return "npol_rule_update_reply" } +func (*NpolRuleUpdateReply) GetCrcString() string { return "e8d4e804" } +func (*NpolRuleUpdateReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} + +func (m *NpolRuleUpdateReply) Size() (size int) { + if m == nil { + return 0 + } + size += 4 // m.Retval + return size +} +func (m *NpolRuleUpdateReply) Marshal(b []byte) ([]byte, error) { + if b == nil { + b = make([]byte, m.Size()) + } + buf := codec.NewBuffer(b) + buf.EncodeInt32(m.Retval) + return buf.Bytes(), nil +} +func (m *NpolRuleUpdateReply) Unmarshal(b []byte) error { + buf := codec.NewBuffer(b) + m.Retval = buf.DecodeInt32() + return nil +} + +func init() { file_npol_binapi_init() } +func file_npol_binapi_init() { + api.RegisterMessage((*NpolConfigurePolicies)(nil), "npol_configure_policies_66fe1335") + api.RegisterMessage((*NpolConfigurePoliciesReply)(nil), "npol_configure_policies_reply_e8d4e804") + api.RegisterMessage((*NpolGetVersion)(nil), "npol_get_version_51077d14") + api.RegisterMessage((*NpolGetVersionReply)(nil), "npol_get_version_reply_9b32cf86") + api.RegisterMessage((*NpolIpsetAddDelMembers)(nil), "npol_ipset_add_del_members_8ad1b2ed") + api.RegisterMessage((*NpolIpsetAddDelMembersReply)(nil), "npol_ipset_add_del_members_reply_e8d4e804") + api.RegisterMessage((*NpolIpsetCreate)(nil), "npol_ipset_create_f948b404") + api.RegisterMessage((*NpolIpsetCreateReply)(nil), "npol_ipset_create_reply_6a43f193") + api.RegisterMessage((*NpolIpsetDelete)(nil), "npol_ipset_delete_ceacdbcb") + api.RegisterMessage((*NpolIpsetDeleteReply)(nil), "npol_ipset_delete_reply_e8d4e804") + api.RegisterMessage((*NpolPolicyCreate)(nil), "npol_policy_create_3441bb97") + api.RegisterMessage((*NpolPolicyCreateReply)(nil), "npol_policy_create_reply_90f27405") + api.RegisterMessage((*NpolPolicyDelete)(nil), "npol_policy_delete_ad833868") + api.RegisterMessage((*NpolPolicyDeleteReply)(nil), "npol_policy_delete_reply_e8d4e804") + api.RegisterMessage((*NpolPolicyUpdate)(nil), "npol_policy_update_21a5f7ef") + api.RegisterMessage((*NpolPolicyUpdateReply)(nil), "npol_policy_update_reply_e8d4e804") + api.RegisterMessage((*NpolRuleCreate)(nil), "npol_rule_create_f113de45") + api.RegisterMessage((*NpolRuleCreateReply)(nil), "npol_rule_create_reply_b48f8052") + api.RegisterMessage((*NpolRuleDelete)(nil), "npol_rule_delete_d19bb6be") + api.RegisterMessage((*NpolRuleDeleteReply)(nil), "npol_rule_delete_reply_e8d4e804") + api.RegisterMessage((*NpolRuleUpdate)(nil), "npol_rule_update_e38bffe2") + api.RegisterMessage((*NpolRuleUpdateReply)(nil), "npol_rule_update_reply_e8d4e804") +} + +// Messages returns list of all messages in this module. +func AllMessages() []api.Message { + return []api.Message{ + (*NpolConfigurePolicies)(nil), + (*NpolConfigurePoliciesReply)(nil), + (*NpolGetVersion)(nil), + (*NpolGetVersionReply)(nil), + (*NpolIpsetAddDelMembers)(nil), + (*NpolIpsetAddDelMembersReply)(nil), + (*NpolIpsetCreate)(nil), + (*NpolIpsetCreateReply)(nil), + (*NpolIpsetDelete)(nil), + (*NpolIpsetDeleteReply)(nil), + (*NpolPolicyCreate)(nil), + (*NpolPolicyCreateReply)(nil), + (*NpolPolicyDelete)(nil), + (*NpolPolicyDeleteReply)(nil), + (*NpolPolicyUpdate)(nil), + (*NpolPolicyUpdateReply)(nil), + (*NpolRuleCreate)(nil), + (*NpolRuleCreateReply)(nil), + (*NpolRuleDelete)(nil), + (*NpolRuleDeleteReply)(nil), + (*NpolRuleUpdate)(nil), + (*NpolRuleUpdateReply)(nil), + } +} diff --git a/vpplink/generated/bindings/npol/npol_rpc.ba.go b/vpplink/generated/bindings/npol/npol_rpc.ba.go new file mode 100644 index 000000000..2802a9932 --- /dev/null +++ b/vpplink/generated/bindings/npol/npol_rpc.ba.go @@ -0,0 +1,131 @@ +// Code generated by GoVPP's binapi-generator. DO NOT EDIT. + +package npol + +import ( + "context" + + api "go.fd.io/govpp/api" +) + +// RPCService defines RPC service npol. +type RPCService interface { + NpolConfigurePolicies(ctx context.Context, in *NpolConfigurePolicies) (*NpolConfigurePoliciesReply, error) + NpolGetVersion(ctx context.Context, in *NpolGetVersion) (*NpolGetVersionReply, error) + NpolIpsetAddDelMembers(ctx context.Context, in *NpolIpsetAddDelMembers) (*NpolIpsetAddDelMembersReply, error) + NpolIpsetCreate(ctx context.Context, in *NpolIpsetCreate) (*NpolIpsetCreateReply, error) + NpolIpsetDelete(ctx context.Context, in *NpolIpsetDelete) (*NpolIpsetDeleteReply, error) + NpolPolicyCreate(ctx context.Context, in *NpolPolicyCreate) (*NpolPolicyCreateReply, error) + NpolPolicyDelete(ctx context.Context, in *NpolPolicyDelete) (*NpolPolicyDeleteReply, error) + NpolPolicyUpdate(ctx context.Context, in *NpolPolicyUpdate) (*NpolPolicyUpdateReply, error) + NpolRuleCreate(ctx context.Context, in *NpolRuleCreate) (*NpolRuleCreateReply, error) + NpolRuleDelete(ctx context.Context, in *NpolRuleDelete) (*NpolRuleDeleteReply, error) + NpolRuleUpdate(ctx context.Context, in *NpolRuleUpdate) (*NpolRuleUpdateReply, error) +} + +type serviceClient struct { + conn api.Connection +} + +func NewServiceClient(conn api.Connection) RPCService { + return &serviceClient{conn} +} + +func (c *serviceClient) NpolConfigurePolicies(ctx context.Context, in *NpolConfigurePolicies) (*NpolConfigurePoliciesReply, error) { + out := new(NpolConfigurePoliciesReply) + err := c.conn.Invoke(ctx, in, out) + if err != nil { + return nil, err + } + return out, api.RetvalToVPPApiError(out.Retval) +} + +func (c *serviceClient) NpolGetVersion(ctx context.Context, in *NpolGetVersion) (*NpolGetVersionReply, error) { + out := new(NpolGetVersionReply) + err := c.conn.Invoke(ctx, in, out) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *serviceClient) NpolIpsetAddDelMembers(ctx context.Context, in *NpolIpsetAddDelMembers) (*NpolIpsetAddDelMembersReply, error) { + out := new(NpolIpsetAddDelMembersReply) + err := c.conn.Invoke(ctx, in, out) + if err != nil { + return nil, err + } + return out, api.RetvalToVPPApiError(out.Retval) +} + +func (c *serviceClient) NpolIpsetCreate(ctx context.Context, in *NpolIpsetCreate) (*NpolIpsetCreateReply, error) { + out := new(NpolIpsetCreateReply) + err := c.conn.Invoke(ctx, in, out) + if err != nil { + return nil, err + } + return out, api.RetvalToVPPApiError(out.Retval) +} + +func (c *serviceClient) NpolIpsetDelete(ctx context.Context, in *NpolIpsetDelete) (*NpolIpsetDeleteReply, error) { + out := new(NpolIpsetDeleteReply) + err := c.conn.Invoke(ctx, in, out) + if err != nil { + return nil, err + } + return out, api.RetvalToVPPApiError(out.Retval) +} + +func (c *serviceClient) NpolPolicyCreate(ctx context.Context, in *NpolPolicyCreate) (*NpolPolicyCreateReply, error) { + out := new(NpolPolicyCreateReply) + err := c.conn.Invoke(ctx, in, out) + if err != nil { + return nil, err + } + return out, api.RetvalToVPPApiError(out.Retval) +} + +func (c *serviceClient) NpolPolicyDelete(ctx context.Context, in *NpolPolicyDelete) (*NpolPolicyDeleteReply, error) { + out := new(NpolPolicyDeleteReply) + err := c.conn.Invoke(ctx, in, out) + if err != nil { + return nil, err + } + return out, api.RetvalToVPPApiError(out.Retval) +} + +func (c *serviceClient) NpolPolicyUpdate(ctx context.Context, in *NpolPolicyUpdate) (*NpolPolicyUpdateReply, error) { + out := new(NpolPolicyUpdateReply) + err := c.conn.Invoke(ctx, in, out) + if err != nil { + return nil, err + } + return out, api.RetvalToVPPApiError(out.Retval) +} + +func (c *serviceClient) NpolRuleCreate(ctx context.Context, in *NpolRuleCreate) (*NpolRuleCreateReply, error) { + out := new(NpolRuleCreateReply) + err := c.conn.Invoke(ctx, in, out) + if err != nil { + return nil, err + } + return out, api.RetvalToVPPApiError(out.Retval) +} + +func (c *serviceClient) NpolRuleDelete(ctx context.Context, in *NpolRuleDelete) (*NpolRuleDeleteReply, error) { + out := new(NpolRuleDeleteReply) + err := c.conn.Invoke(ctx, in, out) + if err != nil { + return nil, err + } + return out, api.RetvalToVPPApiError(out.Retval) +} + +func (c *serviceClient) NpolRuleUpdate(ctx context.Context, in *NpolRuleUpdate) (*NpolRuleUpdateReply, error) { + out := new(NpolRuleUpdateReply) + err := c.conn.Invoke(ctx, in, out) + if err != nil { + return nil, err + } + return out, api.RetvalToVPPApiError(out.Retval) +} diff --git a/vpplink/generated/gen.go b/vpplink/generated/gen.go index 20cd02371..88b30948a 100644 --- a/vpplink/generated/gen.go +++ b/vpplink/generated/gen.go @@ -8,4 +8,4 @@ import ( ) //go:generate go build -buildmode=plugin -o ./.bin/vpplink_plugin.so github.com/calico-vpp/vpplink/pkg -//go:generate go run go.fd.io/govpp/cmd/binapi-generator --no-version-info --no-source-path-info --gen rpc,./.bin/vpplink_plugin.so -o ./bindings --input $VPP_DIR ikev2 gso arp interface ip ipip ipsec ip_neighbor tapv2 nat44_ed cnat af_packet feature ip6_nd punt vxlan af_xdp vlib virtio avf wireguard capo memif acl abf crypto_sw_scheduler sr rdma vmxnet3 pbl memclnt session vpe urpf classify ip_session_redirect +//go:generate go run go.fd.io/govpp/cmd/binapi-generator --no-version-info --no-source-path-info --gen rpc,./.bin/vpplink_plugin.so -o ./bindings --input $VPP_DIR ikev2 gso arp interface ip ipip ipsec ip_neighbor tapv2 nat44_ed cnat af_packet feature ip6_nd punt vxlan af_xdp vlib virtio avf wireguard npol memif acl abf crypto_sw_scheduler sr rdma vmxnet3 pbl memclnt session vpe urpf classify ip_session_redirect diff --git a/vpplink/generated/generate.log b/vpplink/generated/generate.log index 387a64c37..2c2302bd0 100755 --- a/vpplink/generated/generate.log +++ b/vpplink/generated/generate.log @@ -1,11 +1,11 @@ -VPP Version : 25.06.0-25~gfcb92944f +VPP Version : 25.06.0-25~gd73287ef3 Binapi-generator version : v0.11.0 VPP Base commit : 47505bc21 misc: Initial changes for stable/2506 branch ------------------ Cherry picked commits -------------------- -capo: Calico Policies plugin acl: acl-plugin custom policies cnat: [WIP] no k8s maglev from pods pbl: Port based balancer +gerrit:43710/12 npol: Network Policies plugin gerrit:43723/3 session svm: fix session migrate attach data corruption gerrit:43139/5 udp: regrab connected session after transport clone gerrit:43714/5 session: fix handling of closed during migration diff --git a/vpplink/generated/patches/0001-pbl-Port-based-balancer.patch b/vpplink/generated/patches/0001-pbl-Port-based-balancer.patch index 18aaa6697..62a7b2517 100644 --- a/vpplink/generated/patches/0001-pbl-Port-based-balancer.patch +++ b/vpplink/generated/patches/0001-pbl-Port-based-balancer.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Nathan Skrzypczak Date: Tue, 27 Jul 2021 09:41:55 +0200 -Subject: [PATCH 1/5] pbl: Port based balancer +Subject: [PATCH 1/3] pbl: Port based balancer Type: feature @@ -34,10 +34,10 @@ Signed-off-by: Nathan Skrzypczak create mode 100644 src/plugins/pbl/pbl_node.c diff --git a/MAINTAINERS b/MAINTAINERS -index 1117b6da4..5b5522c86 100644 +index d642c742e..43508f00b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -700,6 +700,11 @@ I: svs +@@ -725,6 +725,11 @@ I: svs M: Neale Ranns F: src/plugins/svs/ @@ -1357,5 +1357,5 @@ index 000000000..478584019 + * End: + */ -- -2.39.2 +2.43.0 diff --git a/vpplink/generated/patches/0002-cnat-WIP-no-k8s-maglev-from-pods.patch b/vpplink/generated/patches/0002-cnat-WIP-no-k8s-maglev-from-pods.patch index 646662513..26eadbfdd 100644 --- a/vpplink/generated/patches/0002-cnat-WIP-no-k8s-maglev-from-pods.patch +++ b/vpplink/generated/patches/0002-cnat-WIP-no-k8s-maglev-from-pods.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Nathan Skrzypczak Date: Mon, 8 Mar 2021 19:00:04 +0100 -Subject: [PATCH 2/5] cnat: [WIP] no k8s maglev from pods +Subject: [PATCH 2/3] cnat: [WIP] no k8s maglev from pods Type: improvement @@ -12,7 +12,7 @@ Signed-off-by: Nathan Skrzypczak 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/plugins/cnat/cnat_node_feature.c b/src/plugins/cnat/cnat_node_feature.c -index 76aa89398..fd3b90a1a 100644 +index 9b2c0c2fe..d862a84c0 100644 --- a/src/plugins/cnat/cnat_node_feature.c +++ b/src/plugins/cnat/cnat_node_feature.c @@ -43,6 +43,7 @@ cnat_input_feature_fn (vlib_main_t *vm, vlib_node_runtime_t *node, @@ -45,5 +45,5 @@ index 76aa89398..fd3b90a1a 100644 const dpo_id_t *dpo0; const load_balance_t *lb1; -- -2.39.2 +2.43.0 diff --git a/vpplink/generated/patches/0003-acl-acl-plugin-custom-policies.patch b/vpplink/generated/patches/0003-acl-acl-plugin-custom-policies.patch index 079ce2d11..001ba3e6d 100644 --- a/vpplink/generated/patches/0003-acl-acl-plugin-custom-policies.patch +++ b/vpplink/generated/patches/0003-acl-acl-plugin-custom-policies.patch @@ -1,29 +1,37 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Yourtchenko -Date: Tue, 28 Jul 2020 10:23:06 +0000 -Subject: [PATCH 3/5] acl: acl-plugin custom policies +From: Nathan Skrzypczak +Date: Fri, 10 Oct 2025 12:13:22 +0200 +Subject: [PATCH 3/3] acl: acl-plugin custom policies Type: feature + Change-Id: I3117e84d9e822b68b12265e9261992e4d7f50f0f + Signed-off-by: Andrew Yourtchenko Signed-off-by: Aloys Augustin +Signed-off-by: Nathan Skrzypczak --- - src/plugins/acl/CMakeLists.txt | 2 + - src/plugins/acl/acl.c | 27 +++- - src/plugins/acl/acl.h | 21 ++- - src/plugins/acl/acl_caiop.c | 249 +++++++++++++++++++++++++++++++ - src/plugins/acl/acl_caiop.h | 18 +++ - src/plugins/acl/acl_util.h | 17 +++ - src/plugins/acl/dataplane_node.c | 194 ++++++++++++++++-------- - src/plugins/acl/exported_types.h | 29 +++- - src/plugins/acl/lookup_context.c | 9 +- - 9 files changed, 489 insertions(+), 77 deletions(-) + src/plugins/acl/CMakeLists.txt | 2 + + src/plugins/acl/acl.c | 27 +++- + src/plugins/acl/acl.h | 21 ++- + src/plugins/acl/acl_caiop.c | 249 ++++++++++++++++++++++++++++++ + src/plugins/acl/acl_caiop.h | 18 +++ + src/plugins/acl/acl_util.h | 17 ++ + src/plugins/acl/dataplane_node.c | 194 +++++++++++++++-------- + src/plugins/acl/exported_types.h | 29 +++- + src/plugins/acl/lookup_context.c | 9 +- + src/plugins/npol/npol.h | 1 + + src/plugins/npol/npol_api.c | 7 + + src/plugins/npol/npol_interface.c | 19 +++ + src/plugins/npol/npol_match.c | 8 + + src/plugins/npol/npol_match.h | 3 + + 14 files changed, 527 insertions(+), 77 deletions(-) create mode 100644 src/plugins/acl/acl_caiop.c create mode 100644 src/plugins/acl/acl_caiop.h create mode 100644 src/plugins/acl/acl_util.h diff --git a/src/plugins/acl/CMakeLists.txt b/src/plugins/acl/CMakeLists.txt -index c43dd23ea..44e4e6a60 100644 +index 1bb60d94f..c1faca557 100644 --- a/src/plugins/acl/CMakeLists.txt +++ b/src/plugins/acl/CMakeLists.txt @@ -20,6 +20,8 @@ add_vpp_plugin(acl @@ -36,7 +44,7 @@ index c43dd23ea..44e4e6a60 100644 dataplane_node.c dataplane_node_nonip.c diff --git a/src/plugins/acl/acl.c b/src/plugins/acl/acl.c -index f834425b5..9257289d0 100644 +index fbd947610..fda649fdc 100644 --- a/src/plugins/acl/acl.c +++ b/src/plugins/acl/acl.c @@ -39,6 +39,7 @@ @@ -47,7 +55,7 @@ index f834425b5..9257289d0 100644 acl_main_t acl_main; -@@ -521,6 +522,11 @@ acl_clear_sessions (acl_main_t * am, u32 sw_if_index) +@@ -517,6 +518,11 @@ acl_clear_sessions (acl_main_t * am, u32 sw_if_index) sw_if_index); } @@ -59,7 +67,7 @@ index f834425b5..9257289d0 100644 static int acl_interface_in_enable_disable (acl_main_t * am, u32 sw_if_index, -@@ -605,8 +611,8 @@ acl_stats_intf_counters_enable_disable (acl_main_t * am, int enable_disable) +@@ -601,8 +607,8 @@ acl_stats_intf_counters_enable_disable (acl_main_t * am, int enable_disable) return rv; } @@ -70,7 +78,7 @@ index f834425b5..9257289d0 100644 int is_input, int enable_disable) { if (is_input) -@@ -615,6 +621,12 @@ acl_interface_inout_enable_disable (acl_main_t * am, u32 sw_if_index, +@@ -611,6 +617,12 @@ acl_interface_inout_enable_disable (acl_main_t * am, u32 sw_if_index, return acl_interface_out_enable_disable (am, sw_if_index, enable_disable); } @@ -83,7 +91,7 @@ index f834425b5..9257289d0 100644 static int acl_is_not_defined (acl_main_t * am, u32 acl_list_index) { -@@ -751,8 +763,11 @@ acl_interface_set_inout_acl_list (acl_main_t * am, u32 sw_if_index, +@@ -745,8 +757,11 @@ acl_interface_set_inout_acl_list (acl_main_t * am, u32 sw_if_index, } } /* ensure ACL processing is enabled/disabled as needed */ @@ -96,7 +104,7 @@ index f834425b5..9257289d0 100644 done: clib_bitmap_free (change_acl_bitmap); -@@ -3440,6 +3455,10 @@ acl_plugin_show_sessions (acl_main_t * am, +@@ -3583,6 +3598,10 @@ acl_plugin_show_sessions (acl_main_t * am, ((f64) am->fa_current_cleaner_timer_wait_interval) * 1000.0 / (f64) vm->clib_time.clocks_per_second); vlib_cli_output (vm, "Reclassify sessions: %d", am->reclassify_sessions); @@ -107,7 +115,7 @@ index f834425b5..9257289d0 100644 } static clib_error_t * -@@ -3776,6 +3795,8 @@ acl_init (vlib_main_t * vm) +@@ -3963,6 +3982,8 @@ acl_init (vlib_main_t * vm) ACL_FA_CONN_TABLE_DEFAULT_HASH_MEMORY_SIZE; am->fa_conn_table_max_entries = ACL_FA_CONN_TABLE_DEFAULT_MAX_ENTRIES; am->reclassify_sessions = 0; @@ -466,7 +474,7 @@ index 000000000..843a671ad + * End: + */ diff --git a/src/plugins/acl/dataplane_node.c b/src/plugins/acl/dataplane_node.c -index 4bef8f077..4ccc2a4b1 100644 +index 027afc0f6..eba262cee 100644 --- a/src/plugins/acl/dataplane_node.c +++ b/src/plugins/acl/dataplane_node.c @@ -25,6 +25,7 @@ @@ -477,7 +485,7 @@ index 4bef8f077..4ccc2a4b1 100644 #include #include #include -@@ -318,13 +319,12 @@ acl_fa_node_common_prepare_fn (vlib_main_t * vm, +@@ -316,13 +317,12 @@ acl_fa_node_common_prepare_fn (vlib_main_t * vm, } } @@ -496,7 +504,7 @@ index 4bef8f077..4ccc2a4b1 100644 { u32 n_left; u32 pkts_exist_session = 0; -@@ -465,39 +465,85 @@ acl_fa_inner_node_fn (vlib_main_t * vm, +@@ -463,39 +463,85 @@ acl_fa_inner_node_fn (vlib_main_t * vm, if (acl_check_needed) { @@ -614,7 +622,7 @@ index 4bef8f077..4ccc2a4b1 100644 } b[0]->error = error_node->errors[action]; -@@ -582,11 +628,10 @@ acl_fa_inner_node_fn (vlib_main_t * vm, +@@ -580,11 +626,10 @@ acl_fa_inner_node_fn (vlib_main_t * vm, * if we were had an acl match then we have a counter to increment. * else it is all zeroes, so this will be harmless. */ @@ -630,7 +638,7 @@ index 4bef8f077..4ccc2a4b1 100644 vlib_node_increment_counter (vm, node->node_index, ACL_FA_ERROR_ACL_CHECK, frame->n_vectors); -@@ -602,10 +647,10 @@ acl_fa_inner_node_fn (vlib_main_t * vm, +@@ -600,10 +645,10 @@ acl_fa_inner_node_fn (vlib_main_t * vm, } always_inline uword @@ -645,7 +653,7 @@ index 4bef8f077..4ccc2a4b1 100644 { acl_main_t *am = &acl_main; -@@ -615,25 +660,24 @@ acl_fa_outer_node_fn (vlib_main_t * vm, +@@ -613,25 +658,24 @@ acl_fa_outer_node_fn (vlib_main_t * vm, if (am->reclassify_sessions) { if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE)) @@ -682,7 +690,7 @@ index 4bef8f077..4ccc2a4b1 100644 } } -@@ -646,13 +690,35 @@ acl_fa_node_fn (vlib_main_t * vm, +@@ -644,13 +688,35 @@ acl_fa_node_fn (vlib_main_t * vm, acl_main_t *am = &acl_main; acl_fa_per_worker_data_t *pw = &am->per_worker_data[vm->thread_index]; uword rv; @@ -805,6 +813,110 @@ index 8d1f3f20f..52641f9e7 100644 void acl_plugin_show_lookup_user (u32 user_index) +diff --git a/src/plugins/npol/npol.h b/src/plugins/npol/npol.h +index 2543dd933..958a969fb 100644 +--- a/src/plugins/npol/npol.h ++++ b/src/plugins/npol/npol.h +@@ -31,6 +31,7 @@ typedef struct + typedef struct + { + u32 calico_acl_user_id; ++ acl_plugin_methods_t acl_plugin; + + /* API message ID base */ + u16 msg_id_base; +diff --git a/src/plugins/npol/npol_api.c b/src/plugins/npol/npol_api.c +index 6d2061a75..a9ff343ac 100644 +--- a/src/plugins/npol/npol_api.c ++++ b/src/plugins/npol/npol_api.c +@@ -398,6 +398,13 @@ calpol_init (vlib_main_t *vm) + { + npol_main_t *cpm = &npol_main; + ++ clib_error_t *acl_init_res = acl_plugin_exports_init (&cpm->acl_plugin); ++ if (acl_init_res) ++ return (acl_init_res); ++ ++ cpm->calico_acl_user_id = ++ cpm->acl_plugin.register_user_module ("Network Policy Plugin", NULL, NULL); ++ + cpm->msg_id_base = setup_message_id_table (); + + return (NULL); +diff --git a/src/plugins/npol/npol_interface.c b/src/plugins/npol/npol_interface.c +index 437ae64db..15cfe76e6 100644 +--- a/src/plugins/npol/npol_interface.c ++++ b/src/plugins/npol/npol_interface.c +@@ -15,6 +15,8 @@ int + npol_unconfigure_policies (u32 sw_if_index) + { + npol_interface_config_t *conf; ++ int rv; ++ + conf = vec_elt_at_index (npol_interface_configs, sw_if_index); + if (!conf->enabled) + return 0; +@@ -24,6 +26,15 @@ npol_unconfigure_policies (u32 sw_if_index) + vec_free (conf->tx_policies); + vec_free (conf->profiles); + ++ rv = npol_main.acl_plugin.wip_add_del_custom_access_io_policy ( ++ 0 /* is_add */, sw_if_index, 0 /* is_input */, npol_match_func_acl); ++ if (rv) ++ return rv; ++ rv = npol_main.acl_plugin.wip_add_del_custom_access_io_policy ( ++ 0 /* is_add */, sw_if_index, 1 /* is_input */, npol_match_func_acl); ++ if (rv) ++ return rv; ++ + conf->enabled = 0; + return 0; + } +@@ -57,6 +68,14 @@ npol_configure_policies (u32 sw_if_index, npol_interface_config_t *new_conf) + vec_free (conf->tx_policies); + vec_free (conf->profiles); + } ++ else ++ { ++ npol_main.acl_plugin.wip_add_del_custom_access_io_policy ( ++ 1 /* is_add */, sw_if_index, 0 /* is_input */, npol_match_func_acl); ++ npol_main.acl_plugin.wip_add_del_custom_access_io_policy ( ++ 1 /* is_add */, sw_if_index, 1 /* is_input */, npol_match_func_acl); ++ } ++ + *conf = *new_conf; + conf->enabled = 1; + return 0; +diff --git a/src/plugins/npol/npol_match.c b/src/plugins/npol/npol_match.c +index 645e003e9..6e4e1e2de 100644 +--- a/src/plugins/npol/npol_match.c ++++ b/src/plugins/npol/npol_match.c +@@ -746,4 +746,12 @@ npol_match_func (u32 sw_if_index, u32 is_inbound, fa_5tuple_t *pkt_5tuple, + pkt_5tuple, is_ip6, r_action); + } + ++int ++npol_match_func_acl (void *p_acl_main, u32 sw_if_index, u32 is_inbound, ++ fa_5tuple_opaque_t *pkt_5tuple, int is_ip6, u8 *r_action, ++ u32 *trace_bitmap) ++{ ++ return CLIB_MARCH_FN_SELECT (npol_match) ( ++ sw_if_index, is_inbound, (fa_5tuple_t *) pkt_5tuple, is_ip6, r_action); ++} + #endif /* CLIB_MARCH_VARIANT */ +diff --git a/src/plugins/npol/npol_match.h b/src/plugins/npol/npol_match.h +index 259717c14..d4fd1700a 100644 +--- a/src/plugins/npol/npol_match.h ++++ b/src/plugins/npol/npol_match.h +@@ -14,5 +14,8 @@ + + int npol_match_func (u32 sw_if_index, u32 is_inbound, fa_5tuple_t *pkt_5tuple, + int is_ip6, u8 *r_action); ++int npol_match_func_acl (void *p_acl_main, u32 sw_if_index, u32 is_inbound, ++ fa_5tuple_opaque_t *pkt_5tuple, int is_ip6, ++ u8 *r_action, u32 *trace_bitmap); + + #endif -- -2.39.2 +2.43.0 diff --git a/vpplink/generated/patches/0004-capo-Calico-Policies-plugin.patch b/vpplink/generated/patches/0004-capo-Calico-Policies-plugin.patch deleted file mode 100644 index 8ebd69847..000000000 --- a/vpplink/generated/patches/0004-capo-Calico-Policies-plugin.patch +++ /dev/null @@ -1,5037 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Yourtchenko -Date: Wed, 18 Aug 2021 20:10:22 +0200 -Subject: [PATCH 4/5] capo: Calico Policies plugin - -New plugin that implements Calico policies and profiles in VPP. - -Type: feature - -Change-Id: I49d9c2ee985eb0d4a55ca672da9916dc4afa89ef -Signed-off-by: Andrew Yourtchenko -Signed-off-by: Nathan Skrzypczak -Signed-off-by: Aloys Augustin -Signed-off-by: MathiasRaoul ---- - MAINTAINERS | 5 + - src/plugins/capo/CMakeLists.txt | 28 + - src/plugins/capo/bihash_8_32.h | 112 ++++ - src/plugins/capo/capo.api | 261 ++++++++++ - src/plugins/capo/capo.h | 59 +++ - src/plugins/capo/capo_api.c | 443 ++++++++++++++++ - src/plugins/capo/capo_interface.c | 368 +++++++++++++ - src/plugins/capo/capo_interface.h | 47 ++ - src/plugins/capo/capo_ipset.c | 472 +++++++++++++++++ - src/plugins/capo/capo_ipset.h | 68 +++ - src/plugins/capo/capo_match.c | 737 ++++++++++++++++++++++++++ - src/plugins/capo/capo_match.h | 49 ++ - src/plugins/capo/capo_policy.c | 265 ++++++++++ - src/plugins/capo/capo_policy.h | 58 +++ - src/plugins/capo/capo_rule.c | 509 ++++++++++++++++++ - src/plugins/capo/capo_rule.h | 91 ++++ - src/plugins/capo/capo_test.c | 490 ++++++++++++++++++ - src/plugins/capo/test/test_capo.py | 807 +++++++++++++++++++++++++++++ - 18 files changed, 4869 insertions(+) - create mode 100644 src/plugins/capo/CMakeLists.txt - create mode 100644 src/plugins/capo/bihash_8_32.h - create mode 100644 src/plugins/capo/capo.api - create mode 100644 src/plugins/capo/capo.h - create mode 100644 src/plugins/capo/capo_api.c - create mode 100644 src/plugins/capo/capo_interface.c - create mode 100644 src/plugins/capo/capo_interface.h - create mode 100644 src/plugins/capo/capo_ipset.c - create mode 100644 src/plugins/capo/capo_ipset.h - create mode 100644 src/plugins/capo/capo_match.c - create mode 100644 src/plugins/capo/capo_match.h - create mode 100644 src/plugins/capo/capo_policy.c - create mode 100644 src/plugins/capo/capo_policy.h - create mode 100644 src/plugins/capo/capo_rule.c - create mode 100644 src/plugins/capo/capo_rule.h - create mode 100644 src/plugins/capo/capo_test.c - create mode 100644 src/plugins/capo/test/test_capo.py - -diff --git a/MAINTAINERS b/MAINTAINERS -index 5b5522c86..9155f999d 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -743,6 +743,11 @@ M: Nathan Skrzypczak - M: Neale Ranns - F: src/plugins/cnat - -+Plugin - Calico policies -+I: capo -+M: Aloys Augustin -+F: src/plugins/capo/ -+ - Plugin - Wireguard - I: wireguard - M: Artem Glazychev -diff --git a/src/plugins/capo/CMakeLists.txt b/src/plugins/capo/CMakeLists.txt -new file mode 100644 -index 000000000..9fa10f710 ---- /dev/null -+++ b/src/plugins/capo/CMakeLists.txt -@@ -0,0 +1,28 @@ -+# Copyright (c) 2020 Cisco and/or its affiliates. -+# Licensed under the Apache License, Version 2.0 (the "License"); -+# you may not use this file except in compliance with the License. -+# You may obtain a copy of the License at: -+# -+# http://www.apache.org/licenses/LICENSE-2.0 -+# -+# Unless required by applicable law or agreed to in writing, software -+# distributed under the License is distributed on an "AS IS" BASIS, -+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+# See the License for the specific language governing permissions and -+# limitations under the License. -+ -+add_vpp_plugin(capo -+ SOURCES -+ capo_api.c -+ capo_policy.c -+ capo_rule.c -+ capo_ipset.c -+ capo_match.c -+ capo_interface.c -+ -+ API_TEST_SOURCES -+ capo_test.c -+ -+ API_FILES -+ capo.api -+) -diff --git a/src/plugins/capo/bihash_8_32.h b/src/plugins/capo/bihash_8_32.h -new file mode 100644 -index 000000000..06cdd79e2 ---- /dev/null -+++ b/src/plugins/capo/bihash_8_32.h -@@ -0,0 +1,112 @@ -+/* -+ * Copyright (c) 2015 Cisco and/or its affiliates. -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at: -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+ * See the License for the specific language governing permissions and -+ * limitations under the License. -+ */ -+#undef BIHASH_TYPE -+#undef BIHASH_KVP_PER_PAGE -+#undef BIHASH_32_64_SVM -+#undef BIHASH_ENABLE_STATS -+#undef BIHASH_KVP_AT_BUCKET_LEVEL -+#undef BIHASH_LAZY_INSTANTIATE -+#undef BIHASH_BUCKET_PREFETCH_CACHE_LINES -+ -+#define BIHASH_TYPE _8_32 -+#define BIHASH_KVP_PER_PAGE 4 -+#define BIHASH_KVP_AT_BUCKET_LEVEL 1 -+#define BIHASH_LAZY_INSTANTIATE 0 -+#define BIHASH_BUCKET_PREFETCH_CACHE_LINES 2 -+ -+#ifndef __included_bihash_8_32_h__ -+#define __included_bihash_8_32_h__ -+ -+#include -+#include -+#include -+#include -+#include -+ -+/** 8 octet key, 32 octet key value pair */ -+typedef struct -+{ -+ u64 key; /**< the key */ -+ u64 value[4]; /**< the value */ -+} clib_bihash_kv_8_32_t; -+ -+static inline void -+clib_bihash_mark_free_8_32 (clib_bihash_kv_8_32_t *v) -+{ -+ v->value[0] = 0xFEEDFACE8BADF00DULL; -+} -+ -+/** Decide if a clib_bihash_kv_8_32_t instance is free -+ @param v- pointer to the (key,value) pair -+*/ -+static inline int -+clib_bihash_is_free_8_32 (clib_bihash_kv_8_32_t *v) -+{ -+ if (v->value[0] == 0xFEEDFACE8BADF00DULL) -+ return 1; -+ return 0; -+} -+ -+/** Hash a clib_bihash_kv_8_32_t instance -+ @param v - pointer to the (key,value) pair, hash the key (only) -+*/ -+static inline u64 -+clib_bihash_hash_8_32 (clib_bihash_kv_8_32_t *v) -+{ -+ /* Note: to torture-test linear scan, make this fn return a constant */ -+#ifdef clib_crc32c_uses_intrinsics -+ return clib_crc32c ((u8 *) &v->key, 8); -+#else -+ return clib_xxhash (v->key); -+#endif -+} -+ -+/** Format a clib_bihash_kv_8_32_t instance -+ @param s - u8 * vector under construction -+ @param args (vararg) - the (key,value) pair to format -+ @return s - the u8 * vector under construction -+*/ -+static inline u8 * -+format_bihash_kvp_8_32 (u8 *s, va_list *args) -+{ -+ clib_bihash_kv_8_32_t *v = va_arg (*args, clib_bihash_kv_8_32_t *); -+ -+ s = format (s, "key %lu value %lu %lu %lu %lu", v->key, v->value[0], -+ v->value[1], v->value[2], v->value[3]); -+ return s; -+} -+ -+/** Compare two clib_bihash_kv_8_32_t instances -+ @param a - first key -+ @param b - second key -+*/ -+static inline int -+clib_bihash_key_compare_8_32 (u64 a, u64 b) -+{ -+ return a == b; -+} -+ -+#undef __included_bihash_template_h__ -+#include -+ -+#endif /* __included_bihash_8_32_h__ */ -+ -+/* -+ * fd.io coding-style-patch-verification: ON -+ * -+ * Local Variables: -+ * eval: (c-set-style "gnu") -+ * End: -+ */ -diff --git a/src/plugins/capo/capo.api b/src/plugins/capo/capo.api -new file mode 100644 -index 000000000..b213d1ee6 ---- /dev/null -+++ b/src/plugins/capo/capo.api -@@ -0,0 +1,261 @@ -+/* -+ * Copyright (c) 2020 Cisco and/or its affiliates. -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at: -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+ * See the License for the specific language governing permissions and -+ * limitations under the License. -+ */ -+ -+/** \file -+ This file defines the vpp control-plane API messages -+ used to configure Calico policies -+*/ -+ -+option version = "0.1.0"; -+import "vnet/ip/ip_types.api"; -+import "vnet/fib/fib_types.api"; -+ -+/** \brief Get the plugin version -+ @param client_index - opaque cookie to identify the sender -+ @param context - sender context, to match reply w/ request -+*/ -+ -+define capo_get_version -+{ -+ u32 client_index; -+ u32 context; -+}; -+ -+/** \brief Reply to get the plugin version -+ @param context - returned sender context, to match reply w/ request -+ @param major - Incremented every time a known breaking behavior change is introduced -+ @param minor - Incremented with small changes, may be used to avoid buggy versions -+*/ -+ -+define capo_get_version_reply -+{ -+ u32 context; -+ u32 major; -+ u32 minor; -+}; -+ -+/** \brief Control ping from client to api server request -+ @param client_index - opaque cookie to identify the sender -+ @param context - sender context, to match reply w/ request -+*/ -+define capo_control_ping -+{ -+ u32 client_index; -+ u32 context; -+}; -+ -+/** \brief Control ping from the client to the server response -+ @param client_index - opaque cookie to identify the sender -+ @param context - sender context, to match reply w/ request -+ @param retval - return code for the request -+ @param vpe_pid - the pid of the vpe, returned by the server -+*/ -+define capo_control_ping_reply -+{ -+ u32 context; -+ i32 retval; -+ u32 client_index; -+ u32 vpe_pid; -+}; -+ -+ -+enum capo_ipset_type : u8 { -+ CAPO_IP = 0, /* Each member is an IP address */ -+ CAPO_IP_AND_PORT = 1, /* Each member is ",(tcp|udp):port" (3-tuple) */ -+ CAPO_NET = 2, /* Each member is a CIDR */ -+}; -+ -+typedef capo_three_tuple { -+ vl_api_address_t address; -+ u8 l4_proto; -+ u16 port; -+}; -+ -+union capo_ipset_member_val { -+ vl_api_address_t address; -+ vl_api_prefix_t prefix; -+ vl_api_capo_three_tuple_t tuple; -+}; -+ -+typedef capo_ipset_member { -+ vl_api_capo_ipset_member_val_t val; -+}; -+ -+define capo_ipset_create -+{ -+ u32 client_index; -+ u32 context; -+ vl_api_capo_ipset_type_t type; -+}; -+ -+define capo_ipset_create_reply -+{ -+ u32 context; -+ i32 retval; -+ u32 set_id; -+}; -+ -+ -+autoreply define capo_ipset_add_del_members -+{ -+ u32 client_index; -+ u32 context; -+ u32 set_id; -+ bool is_add; -+ u32 len; -+ vl_api_capo_ipset_member_t members[len]; -+}; -+ -+autoreply define capo_ipset_delete -+{ -+ u32 client_index; -+ u32 context; -+ u32 set_id; -+}; -+ -+enum capo_rule_action : u8 { -+ CAPO_ALLOW = 0, // Accept packet -+ CAPO_DENY, // Drop / reject packet -+ CAPO_LOG, // Ignored for now -+ CAPO_PASS, // Skip following rules, resume evaluation at the policy -+ // with the id configured in capo_configure_policies -+}; -+ -+enum capo_entry_type : u8 { -+ CAPO_CIDR = 0, // simple prefix -+ CAPO_PORT_RANGE, -+ CAPO_PORT_IP_SET, // Points to an ip + proto + port set -+ CAPO_IP_SET, // Points to an ip only set -+}; -+ -+typedef capo_port_range { -+ u16 start; -+ u16 end; // Inclusive, for a single port start==end -+}; -+ -+typedef capo_entry_set_id { -+ u32 set_id; -+}; -+ -+union capo_entry_data { -+ vl_api_prefix_t cidr; -+ vl_api_capo_port_range_t port_range; -+ vl_api_capo_entry_set_id_t set_id; -+}; -+ -+// A rule contains several such entries, each belong to a category -+// categories are: [not_]{src,dst}_{cidr,port_range,port_ip_set,ip_set} -+// (defined byt the 3 first fields in the rule_entry) -+// A rule matches a packet iff: -+// - for every "not" category, the source / destination do not match any entry -+// - for every positive match category, the source / destination matches at -+// least one entry in each category EXCEPT for port ranges and port+ip sets, -+// where the packet only needs to match one entry in either category -+ -+typedef capo_rule_entry { -+ bool is_src; -+ bool is_not; -+ vl_api_capo_entry_type_t type; -+ vl_api_capo_entry_data_t data; -+}; -+ -+enum capo_rule_filter_type : u8 { -+ CAPO_RULE_FILTER_NONE_TYPE = 0, -+ CAPO_RULE_FILTER_ICMP_TYPE, -+ CAPO_RULE_FILTER_ICMP_CODE, -+ CAPO_RULE_FILTER_L4_PROTO, -+}; -+ -+typedef capo_rule_filter { -+ u32 value; -+ vl_api_capo_rule_filter_type_t type; -+ u8 should_match; -+}; -+ -+typedef capo_rule { -+ vl_api_address_family_t af; -+ vl_api_capo_rule_action_t action; -+ vl_api_capo_rule_filter_t filters[3]; -+ u32 num_entries; -+ vl_api_capo_rule_entry_t matches[num_entries]; // List of other criteria -+}; -+ -+define capo_rule_create { -+ u32 client_index; -+ u32 context; -+ vl_api_capo_rule_t rule; -+}; -+ -+autoreply define capo_rule_update { -+ u32 client_index; -+ u32 context; -+ u32 rule_id; -+ vl_api_capo_rule_t rule; -+}; -+ -+define capo_rule_create_reply { -+ u32 context; -+ i32 retval; -+ u32 rule_id; -+}; -+ -+autoreply define capo_rule_delete { -+ u32 client_index; -+ u32 context; -+ u32 rule_id; -+}; -+ -+typedef capo_policy_item { -+ bool is_inbound; // 0 for outbound, 1 for is_inbound -+ u32 rule_id; -+}; -+ -+define capo_policy_create { -+ u32 client_index; -+ u32 context; -+ u32 num_items; -+ vl_api_capo_policy_item_t rules[num_items]; -+}; -+ -+define capo_policy_create_reply { -+ u32 context; -+ i32 retval; -+ u32 policy_id; -+}; -+ -+autoreply define capo_policy_update { -+ u32 client_index; -+ u32 context; -+ u32 policy_id; -+ u32 num_items; -+ vl_api_capo_policy_item_t rules[num_items]; -+}; -+ -+autoreply define capo_policy_delete { -+ u32 client_index; -+ u32 context; -+ u32 policy_id; -+}; -+ -+autoreply define capo_configure_policies { -+ u32 client_index; -+ u32 context; -+ u32 sw_if_index; -+ u32 num_rx_policies; -+ u32 num_tx_policies; -+ u32 total_ids; -+ u8 invert_rx_tx; -+ u32 policy_ids[total_ids]; // rx_policies, then tx_policies, then profiles -+}; -diff --git a/src/plugins/capo/capo.h b/src/plugins/capo/capo.h -new file mode 100644 -index 000000000..5124ec92d ---- /dev/null -+++ b/src/plugins/capo/capo.h -@@ -0,0 +1,59 @@ -+/* -+ * Copyright (c) 2020 Cisco and/or its affiliates. -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at: -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+ * See the License for the specific language governing permissions and -+ * limitations under the License. -+ */ -+ -+#ifndef included_capo_h -+#define included_capo_h -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#define CAPO_INVALID_INDEX ((u32) ~0) -+#define CAPO_DEBUG 0 -+ -+typedef struct -+{ -+ u16 start; -+ u16 end; -+} capo_port_range_t; -+ -+typedef struct -+{ -+ clib_bihash_8_32_t if_config; /* sw_if_index -> capo_interface_config */ -+ -+ u32 calico_acl_user_id; -+ acl_plugin_methods_t acl_plugin; -+ -+ /* API message ID base */ -+ u16 msg_id_base; -+ -+} capo_main_t; -+ -+extern capo_main_t capo_main; -+ -+#endif -+ -+/* -+ * fd.io coding-style-patch-verification: ON -+ * -+ * Local Variables: -+ * eval: (c-set-style "gnu") -+ * End: -+ */ -diff --git a/src/plugins/capo/capo_api.c b/src/plugins/capo/capo_api.c -new file mode 100644 -index 000000000..05ece3cdb ---- /dev/null -+++ b/src/plugins/capo/capo_api.c -@@ -0,0 +1,443 @@ -+/* -+ * Copyright (c) 2020 Cisco and/or its affiliates. -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at: -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+ * See the License for the specific language governing permissions and -+ * limitations under the License. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#define REPLY_MSG_ID_BASE cpm->msg_id_base -+#include -+ -+#define CALICO_POLICY_VERSION_MAJOR 0 -+#define CALICO_POLICY_VERSION_MINOR 0 -+ -+capo_main_t capo_main = { 0 }; -+ -+void -+capo_policy_rule_decode (const vl_api_capo_policy_item_t *in, -+ capo_policy_rule_t *out) -+{ -+ out->rule_id = clib_net_to_host_u32 (in->rule_id); -+ out->direction = in->is_inbound ? VLIB_RX : VLIB_TX; -+} -+ -+int -+capo_ipset_member_decode (capo_ipset_type_t type, -+ const vl_api_capo_ipset_member_t *in, -+ capo_ipset_member_t *out) -+{ -+ switch (type) -+ { -+ case IPSET_TYPE_IP: -+ ip_address_decode2 (&in->val.address, &out->address); -+ break; -+ case IPSET_TYPE_IPPORT: -+ ip_address_decode2 (&in->val.tuple.address, &out->ipport.addr); -+ out->ipport.l4proto = in->val.tuple.l4_proto; -+ out->ipport.port = clib_net_to_host_u16 (in->val.tuple.port); -+ break; -+ case IPSET_TYPE_NET: -+ return ip_prefix_decode2 (&in->val.prefix, &out->prefix); -+ } -+ return 0; -+} -+ -+void -+capo_port_range_decode (const vl_api_capo_port_range_t *in, -+ capo_port_range_t *out) -+{ -+ out->start = clib_net_to_host_u16 (in->start); -+ out->end = clib_net_to_host_u16 (in->end); -+} -+ -+int -+capo_rule_entry_decode (const vl_api_capo_rule_entry_t *in, -+ capo_rule_entry_t *out) -+{ -+ out->flags = 0; -+ if (in->is_src) -+ out->flags |= CAPO_IS_SRC; -+ if (in->is_not) -+ out->flags |= CAPO_IS_NOT; -+ out->type = (capo_entry_type_t) in->type; -+ switch (in->type) -+ { -+ case CAPO_CIDR: -+ return ip_prefix_decode2 (&in->data.cidr, &out->data.cidr); -+ case CAPO_PORT_RANGE: -+ capo_port_range_decode (&in->data.port_range, &out->data.port_range); -+ return 0; -+ case CAPO_PORT_IP_SET: -+ case CAPO_IP_SET: -+ out->data.set_id = clib_net_to_host_u32 (in->data.set_id.set_id); -+ return 0; -+ default: -+ return -1; -+ } -+} -+ -+void -+capo_rule_filter_decode (const vl_api_capo_rule_filter_t *in, -+ capo_rule_filter_t *out) -+{ -+ out->type = (capo_rule_filter_type_t) in->type; -+ out->should_match = in->should_match; -+ out->value = clib_net_to_host_u32 (in->value); -+} -+ -+static void -+vl_api_capo_get_version_t_handler (vl_api_capo_get_version_t *mp) -+{ -+ capo_main_t *cpm = &capo_main; -+ vl_api_capo_get_version_reply_t *rmp; -+ int msg_size = sizeof (*rmp); -+ vl_api_registration_t *reg; -+ -+ reg = vl_api_client_index_to_registration (mp->client_index); -+ if (!reg) -+ return; -+ -+ rmp = vl_msg_api_alloc (msg_size); -+ clib_memset (rmp, 0, msg_size); -+ rmp->_vl_msg_id = ntohs (VL_API_CAPO_GET_VERSION_REPLY + cpm->msg_id_base); -+ rmp->context = mp->context; -+ rmp->major = htonl (CALICO_POLICY_VERSION_MAJOR); -+ rmp->minor = htonl (CALICO_POLICY_VERSION_MINOR); -+ -+ vl_api_send_msg (reg, (u8 *) rmp); -+} -+ -+static void -+vl_api_capo_control_ping_t_handler (vl_api_capo_control_ping_t *mp) -+{ -+ capo_main_t *cpm = &capo_main; -+ vl_api_capo_control_ping_reply_t *rmp; -+ int rv = 0; -+ -+ REPLY_MACRO2 (VL_API_CAPO_CONTROL_PING_REPLY, -+ ({ rmp->vpe_pid = ntohl (getpid ()); })); -+} -+ -+/* NAME: ipset_create */ -+static void -+vl_api_capo_ipset_create_t_handler (vl_api_capo_ipset_create_t *mp) -+{ -+ capo_main_t *cpm = &capo_main; -+ vl_api_capo_ipset_create_reply_t *rmp; -+ int rv = 0; -+ u32 id; -+ -+ id = capo_ipset_create ((capo_ipset_type_t) mp->type); -+ -+ REPLY_MACRO2 (VL_API_CAPO_IPSET_CREATE_REPLY, -+ ({ rmp->set_id = clib_host_to_net_u32 (id); })); -+} -+ -+/* NAME: ipset_add_del_members */ -+static void -+vl_api_capo_ipset_add_del_members_t_handler ( -+ vl_api_capo_ipset_add_del_members_t *mp) -+{ -+ capo_main_t *cpm = &capo_main; -+ vl_api_capo_ipset_add_del_members_reply_t *rmp; -+ u32 set_id, i, n_members; -+ capo_ipset_type_t type; -+ int rv = 0; -+ -+ set_id = clib_net_to_host_u32 (mp->set_id); -+ n_members = clib_net_to_host_u32 (mp->len); -+ -+ rv = capo_ipset_get_type (set_id, &type); -+ if (rv) -+ goto done; -+ -+ for (i = 0; i < n_members; i++) -+ { -+ capo_ipset_member_t _m, *member = &_m; -+ rv = capo_ipset_member_decode (type, &mp->members[i], member); -+ if (rv) -+ break; -+ if (mp->is_add) -+ rv = capo_ipset_add_member (set_id, member); -+ else -+ rv = capo_ipset_del_member (set_id, member); -+ if (rv) -+ break; -+ } -+ -+done: -+ REPLY_MACRO (VL_API_CAPO_IPSET_ADD_DEL_MEMBERS_REPLY); -+} -+ -+/* NAME: ipset_delete */ -+static void -+vl_api_capo_ipset_delete_t_handler (vl_api_capo_ipset_delete_t *mp) -+{ -+ capo_main_t *cpm = &capo_main; -+ vl_api_capo_ipset_delete_reply_t *rmp; -+ u32 set_id; -+ int rv; -+ -+ set_id = clib_net_to_host_u32 (mp->set_id); -+ rv = capo_ipset_delete (set_id); -+ -+ REPLY_MACRO (VL_API_CAPO_IPSET_DELETE_REPLY); -+} -+ -+static int -+vl_api_capo_rule_update_create_handler (u32 *id, vl_api_capo_rule_t *rule) -+{ -+ capo_rule_filter_t *filters = 0, *filter; -+ capo_rule_entry_t *entries = 0, *entry; -+ capo_rule_action_t action; -+ ip_address_family_t af = 0; -+ int rv; -+ u32 n_matches; -+ u32 i; -+ -+ action = (capo_rule_action_t) rule->action; -+ -+ // if ((rv = ip_address_family_decode (rule->af, &af))) -+ // goto done; -+ -+ for (i = 0; i < ARRAY_LEN (rule->filters); i++) -+ { -+ vec_add2 (filters, filter, 1); -+ capo_rule_filter_decode (&rule->filters[i], filter); -+ } -+ -+ n_matches = clib_net_to_host_u32 (rule->num_entries); -+ for (i = 0; i < n_matches; i++) -+ { -+ vec_add2 (entries, entry, 1); -+ if ((rv = capo_rule_entry_decode (&rule->matches[i], entry))) -+ goto done; -+ } -+ -+ rv = capo_rule_update (id, action, af, filters, entries); -+ -+done: -+ vec_free (filters); -+ vec_free (entries); -+ return rv; -+} -+ -+/* NAME: rule_create */ -+static void -+vl_api_capo_rule_create_t_handler (vl_api_capo_rule_create_t *mp) -+{ -+ vl_api_capo_rule_create_reply_t *rmp; -+ capo_main_t *cpm = &capo_main; -+ u32 id = CAPO_INVALID_INDEX; -+ int rv; -+ -+ rv = vl_api_capo_rule_update_create_handler (&id, &mp->rule); -+ -+ REPLY_MACRO2 (VL_API_CAPO_RULE_CREATE_REPLY, -+ ({ rmp->rule_id = clib_host_to_net_u32 (id); })); -+} -+ -+/* NAME: rule_update */ -+static void -+vl_api_capo_rule_update_t_handler (vl_api_capo_rule_update_t *mp) -+{ -+ vl_api_capo_rule_update_reply_t *rmp; -+ capo_main_t *cpm = &capo_main; -+ u32 id; -+ int rv; -+ -+ id = clib_net_to_host_u32 (mp->rule_id); -+ rv = vl_api_capo_rule_update_create_handler (&id, &mp->rule); -+ -+ REPLY_MACRO (VL_API_CAPO_RULE_UPDATE_REPLY); -+} -+ -+/* NAME: rule_delete */ -+static void -+vl_api_capo_rule_delete_t_handler (vl_api_capo_rule_delete_t *mp) -+{ -+ vl_api_capo_rule_delete_reply_t *rmp; -+ capo_main_t *cpm = &capo_main; -+ u32 id; -+ int rv; -+ -+ id = clib_net_to_host_u32 (mp->rule_id); -+ rv = capo_rule_delete (id); -+ -+ REPLY_MACRO (VL_API_CAPO_RULE_DELETE_REPLY); -+} -+ -+static int -+vl_api_capo_policy_update_create_handler (u32 *id, u32 n_rules, -+ vl_api_capo_policy_item_t *api_rules) -+{ -+ capo_policy_rule_t *rules = 0, *rule; -+ int rv; -+ -+ for (u32 i = 0; i < n_rules; i++) -+ { -+ vec_add2 (rules, rule, 1); -+ capo_policy_rule_decode (&api_rules[i], rule); -+ } -+ -+ rv = capo_policy_update (id, rules); -+ -+ vec_free (rules); -+ return rv; -+} -+ -+/* NAME: policy_create */ -+static void -+vl_api_capo_policy_create_t_handler (vl_api_capo_policy_create_t *mp) -+{ -+ vl_api_capo_policy_create_reply_t *rmp; -+ capo_main_t *cpm = &capo_main; -+ u32 id = CAPO_INVALID_INDEX, n_rules; -+ int rv; -+ -+ n_rules = clib_net_to_host_u32 (mp->num_items); -+ rv = vl_api_capo_policy_update_create_handler (&id, n_rules, mp->rules); -+ -+ REPLY_MACRO2 (VL_API_CAPO_POLICY_CREATE_REPLY, -+ ({ rmp->policy_id = clib_host_to_net_u32 (id); })); -+} -+ -+/* NAME: policy_update */ -+static void -+vl_api_capo_policy_update_t_handler (vl_api_capo_policy_update_t *mp) -+{ -+ vl_api_capo_policy_update_reply_t *rmp; -+ capo_main_t *cpm = &capo_main; -+ u32 id, n_rules; -+ int rv; -+ -+ id = clib_net_to_host_u32 (mp->policy_id); -+ n_rules = clib_net_to_host_u32 (mp->num_items); -+ rv = vl_api_capo_policy_update_create_handler (&id, n_rules, mp->rules); -+ -+ REPLY_MACRO (VL_API_CAPO_POLICY_UPDATE_REPLY); -+} -+ -+/* NAME: policy_delete */ -+static void -+vl_api_capo_policy_delete_t_handler (vl_api_capo_policy_delete_t *mp) -+{ -+ vl_api_capo_policy_delete_reply_t *rmp; -+ capo_main_t *cpm = &capo_main; -+ u32 id; -+ int rv = 0; -+ -+ id = clib_net_to_host_u32 (mp->policy_id); -+ rv = capo_policy_delete (id); -+ -+ REPLY_MACRO (VL_API_CAPO_POLICY_DELETE_REPLY); -+} -+ -+/* NAME: configure_policies */ -+static void -+vl_api_capo_configure_policies_t_handler (vl_api_capo_configure_policies_t *mp) -+{ -+ vl_api_capo_configure_policies_reply_t *rmp; -+ capo_main_t *cpm = &capo_main; -+ u32 num_profiles; -+ int rv = -1; -+ int i = 0; -+ -+ mp->sw_if_index = clib_net_to_host_u32 (mp->sw_if_index); -+ mp->num_rx_policies = clib_net_to_host_u32 (mp->num_rx_policies); -+ mp->num_tx_policies = clib_net_to_host_u32 (mp->num_tx_policies); -+ mp->total_ids = clib_net_to_host_u32 (mp->total_ids); -+ num_profiles = mp->total_ids - mp->num_rx_policies - mp->num_tx_policies; -+ for (i = 0; i < mp->total_ids; i++) -+ { -+ mp->policy_ids[i] = clib_net_to_host_u32 (mp->policy_ids[i]); -+ } -+ -+ rv = capo_configure_policies (mp->sw_if_index, mp->num_rx_policies, -+ mp->num_tx_policies, num_profiles, -+ mp->policy_ids, mp->invert_rx_tx); -+ -+ REPLY_MACRO (VL_API_CAPO_CONFIGURE_POLICIES_REPLY); -+} -+ -+/* Set up the API message handling tables */ -+#include -+#include -+ -+#include -+#include -+ -+/* Declare message IDs */ -+#include -+#include -+#undef vl_print -+#define vl_print(handle, ...) -+#undef vl_print -+#define vl_endianfun /* define message structures */ -+#include -+#undef vl_endianfun -+ -+static clib_error_t * -+calpol_init (vlib_main_t *vm) -+{ -+ capo_main_t *cpm = &capo_main; -+ -+ clib_error_t *acl_init_res = acl_plugin_exports_init (&cpm->acl_plugin); -+ if (acl_init_res) -+ return (acl_init_res); -+ -+ cpm->calico_acl_user_id = -+ cpm->acl_plugin.register_user_module ("Calico Policy Plugin", NULL, NULL); -+ -+ cpm->msg_id_base = setup_message_id_table (); -+ -+ clib_bihash_init_8_32 (&cpm->if_config, "capo interfaces", 512, 1 << 20); -+ -+ return (NULL); -+} -+ -+static clib_error_t * -+calpol_plugin_config (vlib_main_t *vm, unformat_input_t *input) -+{ -+ return NULL; -+} -+ -+VLIB_PLUGIN_REGISTER () = { -+ .version = VPP_BUILD_VER, -+ .description = "Calico Policy", -+}; -+ -+VLIB_CONFIG_FUNCTION (calpol_plugin_config, "calico-policy-plugin"); -+ -+VLIB_INIT_FUNCTION (calpol_init) = { -+ .runs_after = VLIB_INITS ("acl_init"), -+}; -+ -+/* -+ * fd.io coding-style-patch-verification: ON -+ * -+ * Local Variables: -+ * eval: (c-set-style "gnu") -+ * End: -+ */ -diff --git a/src/plugins/capo/capo_interface.c b/src/plugins/capo/capo_interface.c -new file mode 100644 -index 000000000..787bdfa2d ---- /dev/null -+++ b/src/plugins/capo/capo_interface.c -@@ -0,0 +1,368 @@ -+/* -+ * Copyright (c) 2020 Cisco and/or its affiliates. -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at: -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+ * See the License for the specific language governing permissions and -+ * limitations under the License. -+ */ -+ -+#include -+#include -+#include -+ -+uword unformat_sw_if_index (unformat_input_t *input, va_list *args); -+ -+static int -+print_capo_interface2 (clib_bihash_kv_8_32_t *kv, void *arg) -+{ -+ u8 **s = (u8 **) arg; -+ u32 sw_if_index = kv->key; -+ capo_interface_config_t *conf = (capo_interface_config_t *) kv->value; -+ *s = format (*s, "%U", format_capo_interface, sw_if_index, conf); -+ return BIHASH_WALK_CONTINUE; -+} -+ -+void -+capo_interface_print_current_state () -+{ -+ u8 *s = 0; -+ clib_bihash_foreach_key_value_pair_8_32 (&capo_main.if_config, -+ print_capo_interface2, (void *) &s); -+#if CAPO_DEBUG > 0 -+ clib_warning ("Current interface state:\n%s", s); -+#endif -+ vec_free (s); -+} -+ -+int -+capo_configure_policies (u32 sw_if_index, u32 num_rx_policies, -+ u32 num_tx_policies, u32 num_profiles, -+ u32 *policy_ids, u8 invert_rx_tx) -+{ -+ clib_bihash_kv_8_32_t kv = { sw_if_index, { 0 } }; -+ capo_interface_config_t *conf = (capo_interface_config_t *) &kv.value; -+ capo_interface_config_t *old_conf; -+ u32 found = 0, i = 0; -+ -+ if (pool_is_free_index (vnet_get_main ()->interface_main.sw_interfaces, -+ sw_if_index)) -+ { -+#if CAPO_DEBUG > 0 -+ clib_warning ( -+ "configuring policies for interface %u which doesn't exist", -+ sw_if_index); -+#endif -+ return VNET_API_ERROR_INVALID_SW_IF_INDEX; -+ } -+ -+ if (clib_bihash_search_8_32 (&capo_main.if_config, &kv, &kv) >= 0) -+ { -+ old_conf = (capo_interface_config_t *) &kv.value; -+ vec_free (old_conf->rx_policies); -+ vec_free (old_conf->tx_policies); -+ vec_free (old_conf->profiles); -+ found = 1; -+ } -+ -+ for (i = 0; i < num_rx_policies + num_tx_policies + num_profiles; i++) -+ if (pool_is_free_index (capo_policies, policy_ids[i])) -+ goto error; -+ -+ conf->invert_rx_tx = invert_rx_tx; -+ vec_resize (conf->rx_policies, num_rx_policies); -+ for (i = 0; i < num_rx_policies; i++) -+ conf->rx_policies[i] = policy_ids[i]; -+ vec_resize (conf->tx_policies, num_tx_policies); -+ for (i = 0; i < num_tx_policies; i++) -+ conf->tx_policies[i] = policy_ids[num_rx_policies + i]; -+ vec_resize (conf->profiles, num_profiles); -+ for (i = 0; i < num_profiles; i++) -+ conf->profiles[i] = policy_ids[num_rx_policies + num_tx_policies + i]; -+ -+ clib_bihash_add_del_8_32 (&capo_main.if_config, &kv, 1 /* is_add */); -+ -+ if (!found) -+ { -+ capo_main.acl_plugin.wip_add_del_custom_access_io_policy ( -+ 1 /* is_add */, sw_if_index, 0 /* is_input */, capo_match_func); -+ capo_main.acl_plugin.wip_add_del_custom_access_io_policy ( -+ 1 /* is_add */, sw_if_index, 1 /* is_input */, capo_match_func); -+ } -+ -+ capo_main.acl_plugin.wip_clear_sessions (sw_if_index); -+ return 0; -+ -+error: -+#if CAPO_DEBUG > 0 -+ clib_warning ("error configuring policies for %u", sw_if_index); -+#endif -+ vec_resize (conf->rx_policies, 0); -+ vec_resize (conf->tx_policies, 0); -+ vec_resize (conf->profiles, 0); -+ return 1; -+} -+ -+static clib_error_t * -+capo_sw_interface_add_del (vnet_main_t *vnm, u32 sw_if_index, u32 is_add) -+{ -+ clib_bihash_kv_8_32_t kv = { sw_if_index, { 0 } }; -+ capo_interface_config_t *conf = (capo_interface_config_t *) &kv.value; -+ int __clib_unused rv = 0; -+ -+ if (is_add) -+ return NULL; -+ -+ if (clib_bihash_search_8_32 (&capo_main.if_config, &kv, &kv) >= 0) -+ { -+ conf = (capo_interface_config_t *) &kv.value; -+ vec_free (conf->rx_policies); -+ vec_free (conf->tx_policies); -+ vec_free (conf->profiles); -+ } -+ -+#if CAPO_DEBUG > 0 -+ clib_warning ("unconfiguring policies for if %u deleted", sw_if_index); -+#endif -+ clib_bihash_add_del_8_32 (&capo_main.if_config, &kv, 0 /* is_add */); -+ rv = capo_main.acl_plugin.wip_add_del_custom_access_io_policy ( -+ 0 /* is_add */, sw_if_index, 0 /* is_input */ -+ , -+ capo_match_func); -+#if CAPO_DEBUG > 0 -+ if (rv) -+ clib_warning ("error deleting caiop (output): %d", rv); -+#endif -+ rv = capo_main.acl_plugin.wip_add_del_custom_access_io_policy ( -+ 0 /* is_add */, sw_if_index, 1 /* is_input */ -+ , -+ capo_match_func); -+#if CAPO_DEBUG > 0 -+ if (rv) -+ clib_warning ("error deleting caiop (input): %d", rv); -+#endif -+ return NULL; -+} -+ -+VNET_SW_INTERFACE_ADD_DEL_FUNCTION (capo_sw_interface_add_del); -+ -+u8 * -+format_capo_interface (u8 *s, va_list *args) -+{ -+ u32 sw_if_index = va_arg (*args, u32); -+ capo_interface_config_t *conf = va_arg (*args, capo_interface_config_t *); -+ vnet_main_t *vnm = vnet_get_main (); -+ capo_policy_t *policy = NULL; -+ u32 *rx_policies = conf->rx_policies; -+ u32 *tx_policies = conf->tx_policies; -+ u32 i; -+ -+ s = format (s, "[%U sw_if_index=%u ", format_vnet_sw_if_index_name, vnm, -+ sw_if_index, sw_if_index); -+ if (conf->invert_rx_tx) -+ { -+ s = format (s, "inverted"); -+ rx_policies = conf->tx_policies; -+ tx_policies = conf->rx_policies; -+ } -+ ip4_address_t *ip4 = 0; -+ ip4 = ip4_interface_first_address (&ip4_main, sw_if_index, 0); -+ if (ip4) -+ s = format (s, " addr=%U", format_ip4_address, ip4); -+ ip6_address_t *ip6 = 0; -+ ip6 = ip6_interface_first_address (&ip6_main, sw_if_index); -+ if (ip6) -+ s = format (s, " addr6=%U", format_ip6_address, ip6); -+ s = format (s, "]\n"); -+ if (vec_len (rx_policies)) -+ s = format (s, " rx:\n"); -+ vec_foreach_index (i, rx_policies) -+ { -+ policy = capo_policy_get_if_exists (rx_policies[i]); -+ s = format (s, " %U", format_capo_policy, policy, 4 /* indent */, -+ CAPO_POLICY_ONLY_RX, conf->invert_rx_tx); -+ } -+ if (vec_len (tx_policies)) -+ s = format (s, " tx:\n"); -+ vec_foreach_index (i, tx_policies) -+ { -+ policy = capo_policy_get_if_exists (tx_policies[i]); -+ s = format (s, " %U", format_capo_policy, policy, 4 /* indent */, -+ CAPO_POLICY_ONLY_TX, conf->invert_rx_tx); -+ } -+ if (vec_len (conf->profiles)) -+ s = format (s, " profiles:\n"); -+ vec_foreach_index (i, conf->profiles) -+ { -+ policy = capo_policy_get_if_exists (conf->profiles[i]); -+ s = format (s, " %U", format_capo_policy, policy, 4 /* indent */, -+ CAPO_POLICY_VERBOSE, conf->invert_rx_tx); -+ } -+ return s; -+} -+ -+int -+print_capo_interface (clib_bihash_kv_8_32_t *kv, void *arg) -+{ -+ vlib_main_t *vm = (vlib_main_t *) arg; -+ u32 sw_if_index = kv->key; -+ capo_interface_config_t *conf = (capo_interface_config_t *) kv->value; -+ vlib_cli_output (vm, "%U", format_capo_interface, sw_if_index, conf); -+ return BIHASH_WALK_CONTINUE; -+} -+ -+static clib_error_t * -+capo_interface_show_cmd_fn (vlib_main_t *vm, unformat_input_t *input, -+ vlib_cli_command_t *cmd) -+{ -+ vlib_cli_output (vm, "Interfaces with policies configured:"); -+ clib_bihash_foreach_key_value_pair_8_32 (&capo_main.if_config, -+ print_capo_interface, vm); -+ return NULL; -+} -+ -+VLIB_CLI_COMMAND (capo_policies_show_cmd, static) = { -+ .path = "show capo interfaces", -+ .function = capo_interface_show_cmd_fn, -+ .short_help = "show capo interfaces", -+}; -+ -+static clib_error_t * -+capo_interface_clear_cmd_fn (vlib_main_t *vm, unformat_input_t *input, -+ vlib_cli_command_t *cmd) -+{ -+ unformat_input_t _line_input, *line_input = &_line_input; -+ clib_error_t *error = 0; -+ u32 sw_if_index = CAPO_INVALID_INDEX; -+ int rv; -+ -+ if (!unformat_user (input, unformat_line_input, line_input)) -+ return clib_error_return (0, "missing parameters"); -+ -+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) -+ { -+ if (unformat (line_input, "%U", unformat_sw_if_index, NULL, -+ &sw_if_index)) -+ ; -+ else if (unformat (line_input, "sw_if_index %d", &sw_if_index)) -+ ; -+ else -+ { -+ error = clib_error_return (0, "unknown input '%U'", -+ format_unformat_error, line_input); -+ goto done; -+ } -+ } -+ -+ if (sw_if_index == CAPO_INVALID_INDEX) -+ { -+ error = clib_error_return (0, "interface not specified"); -+ goto done; -+ } -+ -+ rv = capo_configure_policies (sw_if_index, 0, 0, 0, NULL, 0); -+ if (rv) -+ error = -+ clib_error_return (0, "capo_configure_policies errored with %d", rv); -+ else -+ vlib_cli_output (vm, "capo interface %d cleared", sw_if_index); -+ -+done: -+ unformat_free (line_input); -+ return error; -+} -+ -+VLIB_CLI_COMMAND (capo_interface_clear_cmd, static) = { -+ .path = "capo interface clear", -+ .function = capo_interface_clear_cmd_fn, -+ .short_help = "capo interface clear [interface | sw_if_index N]", -+}; -+ -+static clib_error_t * -+capo_interface_configure_cmd_fn (vlib_main_t *vm, unformat_input_t *input, -+ vlib_cli_command_t *cmd) -+{ -+ unformat_input_t _line_input, *line_input = &_line_input; -+ clib_error_t *error = 0; -+ u32 sw_if_index = CAPO_INVALID_INDEX; -+ u32 num_rx_policies = 0; -+ u32 num_tx_policies = 0; -+ u32 policy_id; -+ u32 *policy_list = NULL; -+ u8 invert_rx_tx = 0; -+ int rv; -+ -+ if (!unformat_user (input, unformat_line_input, line_input)) -+ return clib_error_return (0, "missing parameters"); -+ -+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) -+ { -+ if (unformat (line_input, "%U", unformat_sw_if_index, NULL, -+ &sw_if_index)) -+ ; -+ else if (unformat (line_input, "sw_if_index %d", &sw_if_index)) -+ ; -+ else if (unformat (line_input, "rx %d", &num_rx_policies)) -+ ; -+ else if (unformat (line_input, "tx %d", &num_tx_policies)) -+ ; -+ else if (unformat (line_input, "invert")) -+ invert_rx_tx = 1; -+ else if (unformat (line_input, "%d", &policy_id)) -+ vec_add1 (policy_list, policy_id); -+ else -+ { -+ error = clib_error_return (0, "unknown input '%U'", -+ format_unformat_error, line_input); -+ goto done; -+ } -+ } -+ -+ if (sw_if_index == CAPO_INVALID_INDEX) -+ { -+ error = clib_error_return (0, "interface not specified"); -+ goto done; -+ } -+ if (!vec_len (policy_list)) -+ { -+ error = clib_error_return (0, "no policies specified"); -+ goto done; -+ } -+ -+ rv = capo_configure_policies (sw_if_index, num_rx_policies, num_tx_policies, -+ vec_len (policy_list) - num_rx_policies - -+ num_tx_policies, -+ policy_list, invert_rx_tx); -+ -+ if (rv) -+ error = -+ clib_error_return (0, "capo_configure_policies errored with %d", rv); -+ else -+ vlib_cli_output (vm, "capo interface %d configured", sw_if_index); -+ -+done: -+ unformat_free (line_input); -+ vec_free (policy_list); -+ return error; -+} -+ -+VLIB_CLI_COMMAND (capo_interface_configure_cmd, static) = { -+ .path = "capo interface configure", -+ .function = capo_interface_configure_cmd_fn, -+ .short_help = "capo interface configure [interface | sw_if_index N] rx " -+ " tx ...", -+}; -+ -+/* -+ * fd.io coding-style-patch-verification: ON -+ * -+ * Local Variables: -+ * eval: (c-set-style "gnu") -+ * End: -+ */ -diff --git a/src/plugins/capo/capo_interface.h b/src/plugins/capo/capo_interface.h -new file mode 100644 -index 000000000..8248953b7 ---- /dev/null -+++ b/src/plugins/capo/capo_interface.h -@@ -0,0 +1,47 @@ -+/* -+ * Copyright (c) 2020 Cisco and/or its affiliates. -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at: -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+ * See the License for the specific language governing permissions and -+ * limitations under the License. -+ */ -+ -+#ifndef included_capo_interface_h -+#define included_capo_interface_h -+ -+#include -+ -+typedef struct -+{ -+ u32 *rx_policies; -+ u32 *tx_policies; -+ u32 *profiles; -+ u8 invert_rx_tx; -+} capo_interface_config_t; -+ -+int capo_configure_policies (u32 sw_if_index, u32 num_rx_policies, -+ u32 num_tx_policies, u32 num_profiles, -+ u32 *policy_ids, u8 invert_rx_tx); -+u8 *format_capo_interface (u8 *s, va_list *args); -+ -+STATIC_ASSERT (sizeof (capo_interface_config_t) <= -+ (sizeof (clib_bihash_kv_8_32_t) - -+ STRUCT_OFFSET_OF (clib_bihash_kv_8_32_t, value)), -+ "bihash value size"); -+ -+#endif -+ -+/* -+ * fd.io coding-style-patch-verification: ON -+ * -+ * Local Variables: -+ * eval: (c-set-style "gnu") -+ * End: -+ */ -diff --git a/src/plugins/capo/capo_ipset.c b/src/plugins/capo/capo_ipset.c -new file mode 100644 -index 000000000..32db3b957 ---- /dev/null -+++ b/src/plugins/capo/capo_ipset.c -@@ -0,0 +1,472 @@ -+/* -+ * Copyright (c) 2020 Cisco and/or its affiliates. -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at: -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+ * See the License for the specific language governing permissions and -+ * limitations under the License. -+ */ -+ -+#include -+#include -+ -+capo_ipset_t *capo_ipsets; -+ -+u8 * -+format_capo_ipport (u8 *s, va_list *args) -+{ -+ capo_ipport_t *ipport = va_arg (*args, capo_ipport_t *); -+ return format (s, "%U %U;%u", format_ip_protocol, ipport->l4proto, -+ format_ip_address, &ipport->addr, ipport->port); -+} -+ -+u8 * -+format_capo_ipset_member (u8 *s, va_list *args) -+{ -+ capo_ipset_member_t *member = va_arg (*args, capo_ipset_member_t *); -+ capo_ipset_type_t type = va_arg (*args, capo_ipset_type_t); -+ switch (type) -+ { -+ case IPSET_TYPE_IP: -+ return format (s, "%U", format_ip_address, &member->address); -+ case IPSET_TYPE_IPPORT: -+ return format (s, "%U", format_capo_ipport, &member->ipport); -+ case IPSET_TYPE_NET: -+ return format (s, "%U", format_ip_prefix, &member->prefix); -+ default: -+ return format (s, "unknown type"); -+ } -+} -+ -+uword -+unformat_capo_ipport (unformat_input_t *input, va_list *args) -+{ -+ capo_ipport_t *ipport = va_arg (*args, capo_ipport_t *); -+ u32 proto; -+ u32 port; -+ if (unformat (input, "%U %U %d", unformat_ip_protocol, &proto, -+ unformat_ip_address, &ipport->addr, &port)) -+ ; -+ else -+ return 0; -+ -+ ipport->port = port; -+ ipport->l4proto = (u8) proto; -+ return 1; -+} -+ -+u8 * -+format_capo_ipset_type (u8 *s, va_list *args) -+{ -+ capo_ipset_type_t type = va_arg (*args, capo_ipset_type_t); -+ switch (type) -+ { -+ case IPSET_TYPE_IP: -+ return format (s, "ip"); -+ case IPSET_TYPE_IPPORT: -+ return format (s, "ip+port"); -+ case IPSET_TYPE_NET: -+ return format (s, "prefix"); -+ default: -+ return format (s, "unknownipsettype"); -+ } -+} -+ -+uword -+unformat_capo_ipset_member (unformat_input_t *input, va_list *args) -+{ -+ capo_ipset_member_t *member = va_arg (*args, capo_ipset_member_t *); -+ capo_ipset_type_t *type = va_arg (*args, capo_ipset_type_t *); -+ if (unformat_user (input, unformat_ip_prefix, &member->prefix)) -+ *type = IPSET_TYPE_NET; -+ else if (unformat_user (input, unformat_ip_address, &member->address)) -+ *type = IPSET_TYPE_IP; -+ else if (unformat_user (input, unformat_capo_ipport, &member->ipport)) -+ *type = IPSET_TYPE_IPPORT; -+ else -+ return 0; -+ -+ return 1; -+} -+ -+u8 * -+format_capo_ipset (u8 *s, va_list *args) -+{ -+ capo_ipset_t *ipset = va_arg (*args, capo_ipset_t *); -+ capo_ipset_member_t *member; -+ -+ if (ipset == NULL) -+ return format (s, "deleted ipset"); -+ -+ s = format (s, "[ipset#%d;%U;", ipset - capo_ipsets, format_capo_ipset_type, -+ ipset->type); -+ -+ pool_foreach (member, ipset->members) -+ s = format (s, "%U,", format_capo_ipset_member, member, ipset->type); -+ -+ s = format (s, "]"); -+ -+ return (s); -+} -+ -+capo_ipset_t * -+capo_ipsets_get_if_exists (u32 index) -+{ -+ if (pool_is_free_index (capo_ipsets, index)) -+ return (NULL); -+ return pool_elt_at_index (capo_ipsets, index); -+} -+ -+u32 -+capo_ipset_create (capo_ipset_type_t type) -+{ -+ capo_ipset_t *ipset; -+ pool_get (capo_ipsets, ipset); -+ ipset->type = type; -+ ipset->members = NULL; -+ return ipset - capo_ipsets; -+} -+ -+int -+capo_ipset_delete (u32 id) -+{ -+ capo_ipset_t *ipset; -+ ipset = capo_ipsets_get_if_exists (id); -+ if (NULL == ipset) -+ return VNET_API_ERROR_NO_SUCH_ENTRY; -+ -+ pool_free (ipset->members); -+ pool_put (capo_ipsets, ipset); -+ return 0; -+} -+ -+int -+capo_ipset_get_type (u32 id, capo_ipset_type_t *type) -+{ -+ capo_ipset_t *ipset; -+ ipset = capo_ipsets_get_if_exists (id); -+ if (NULL == ipset) -+ return VNET_API_ERROR_NO_SUCH_ENTRY; -+ -+ *type = ipset->type; -+ return 0; -+} -+ -+int -+capo_ipset_add_member (u32 ipset_id, capo_ipset_member_t *member) -+{ -+ capo_ipset_member_t *m; -+ capo_ipset_t *ipset = &capo_ipsets[ipset_id]; -+ -+ if (pool_is_free (capo_ipsets, ipset)) -+ { -+ return 1; -+ } -+ -+ /* zero so that we can memcmp later */ -+ pool_get_zero (ipset->members, m); -+ clib_memcpy (m, member, sizeof (*m)); -+ return 0; -+} -+ -+static size_t -+capo_ipset_member_cmp (capo_ipset_member_t *m1, capo_ipset_member_t *m2, -+ capo_ipset_type_t type) -+{ -+ switch (type) -+ { -+ case IPSET_TYPE_IP: -+ return ip_address_cmp (&m1->address, &m2->address); -+ case IPSET_TYPE_IPPORT: -+ return ((m1->ipport.port == m2->ipport.port) && -+ (m1->ipport.l4proto == m2->ipport.l4proto) && -+ ip_address_cmp (&m1->ipport.addr, &m2->ipport.addr)); -+ case IPSET_TYPE_NET: -+ return ip_prefix_cmp (&m1->prefix, &m2->prefix); -+ default: -+ return 1; -+ } -+} -+ -+int -+capo_ipset_del_member (u32 id, capo_ipset_member_t *member) -+{ -+ index_t *index, *indexes = NULL; -+ capo_ipset_member_t *m; -+ capo_ipset_t *ipset; -+ -+ ipset = capo_ipsets_get_if_exists (id); -+ if (NULL == ipset) -+ return VNET_API_ERROR_NO_SUCH_ENTRY; -+ -+ pool_foreach (m, ipset->members) -+ { -+ if (!capo_ipset_member_cmp (m, member, ipset->type)) -+ vec_add1 (indexes, m - ipset->members); -+ } -+ -+ vec_foreach (index, indexes) -+ pool_put_index (ipset->members, *index); -+ vec_free (indexes); -+ -+ return 0; -+} -+ -+static clib_error_t * -+capo_ipsets_show_cmd_fn (vlib_main_t *vm, unformat_input_t *input, -+ vlib_cli_command_t *cmd) -+{ -+ capo_ipset_t *ipset; -+ -+ pool_foreach (ipset, capo_ipsets) -+ vlib_cli_output (vm, "%U", format_capo_ipset, ipset); -+ -+ return 0; -+} -+ -+VLIB_CLI_COMMAND (capo_ipsets_show_cmd, static) = { -+ .path = "show capo ipsets", -+ .function = capo_ipsets_show_cmd_fn, -+ .short_help = "show capo ipsets", -+}; -+ -+static clib_error_t * -+capo_ipsets_add_cmd_fn (vlib_main_t *vm, unformat_input_t *input, -+ vlib_cli_command_t *cmd) -+{ -+ unformat_input_t _line_input, *line_input = &_line_input; -+ capo_ipset_member_t tmp, *members = 0, *member; -+ clib_error_t *error = 0; -+ capo_ipset_type_t type; -+ capo_ipset_t *ipset; -+ u32 id; -+ int rv; -+ -+ id = capo_ipset_create ((capo_ipset_type_t) ~0); -+ vlib_cli_output (vm, "capo ipset %d added", id); -+ -+ if (!unformat_user (input, unformat_line_input, line_input)) -+ return 0; -+ -+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) -+ { -+ if (unformat (line_input, "%U", unformat_capo_ipset_member, &tmp, &type)) -+ vec_add1 (members, tmp); -+ else -+ { -+ error = clib_error_return (0, "unknown input '%U'", -+ format_unformat_error, line_input); -+ goto done; -+ } -+ } -+ -+ ipset = pool_elt_at_index (capo_ipsets, id); -+ ipset->type = type; -+ -+ vec_foreach (member, members) -+ { -+ rv = capo_ipset_add_member (id, member); -+ if (rv) -+ error = clib_error_return (0, "capo_ipset_add_member error %d", rv); -+ } -+ -+done: -+ vec_free (members); -+ unformat_free (line_input); -+ return error; -+} -+ -+VLIB_CLI_COMMAND (capo_ipsets_add_cmd, static) = { -+ .path = "capo ipset add", -+ .function = capo_ipsets_add_cmd_fn, -+ .short_help = "capo ipset add [prefix|proto ip port|ip]", -+}; -+ -+static clib_error_t * -+capo_ipsets_del_cmd_fn (vlib_main_t *vm, unformat_input_t *input, -+ vlib_cli_command_t *cmd) -+{ -+ unformat_input_t _line_input, *line_input = &_line_input; -+ clib_error_t *error = 0; -+ u32 id = CAPO_INVALID_INDEX; -+ int rv; -+ -+ if (!unformat_user (input, unformat_line_input, line_input)) -+ return clib_error_return (0, "missing ipset id"); -+ -+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) -+ { -+ if (unformat (line_input, "%u", &id)) -+ ; -+ else -+ { -+ error = clib_error_return (0, "unknown input '%U'", -+ format_unformat_error, line_input); -+ goto done; -+ } -+ } -+ -+ if (CAPO_INVALID_INDEX == id) -+ { -+ error = clib_error_return (0, "missing ipset id"); -+ goto done; -+ } -+ -+ rv = capo_ipset_delete (id); -+ if (rv) -+ error = clib_error_return (0, "capo_ipset_delete errored with %d", rv); -+ -+done: -+ unformat_free (line_input); -+ return error; -+} -+ -+VLIB_CLI_COMMAND (capo_ipsets_del_cmd, static) = { -+ .path = "capo ipset del", -+ .function = capo_ipsets_del_cmd_fn, -+ .short_help = "capo ipset del [id]", -+}; -+ -+static clib_error_t * -+capo_ipsets_add_member_cmd_fn (vlib_main_t *vm, unformat_input_t *input, -+ vlib_cli_command_t *cmd) -+{ -+ unformat_input_t _line_input, *line_input = &_line_input; -+ capo_ipset_member_t tmp, *members = 0, *member; -+ u32 id = CAPO_INVALID_INDEX; -+ clib_error_t *error = 0; -+ capo_ipset_type_t type; -+ capo_ipset_t *ipset; -+ int rv; -+ -+ if (!unformat_user (input, unformat_line_input, line_input)) -+ return clib_error_return (0, "missing parameters"); -+ -+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) -+ { -+ if (unformat (line_input, "id %u", &id)) -+ ; -+ else if (unformat (line_input, "%U", unformat_capo_ipset_member, &tmp, -+ &type)) -+ vec_add1 (members, tmp); -+ else -+ { -+ error = clib_error_return (0, "unknown input '%U'", -+ format_unformat_error, line_input); -+ goto done; -+ } -+ } -+ -+ if (CAPO_INVALID_INDEX == id) -+ { -+ error = clib_error_return (0, "missing ipset id"); -+ goto done; -+ } -+ -+ ipset = capo_ipsets_get_if_exists (id); -+ if (NULL == ipset) -+ return clib_error_return (0, "ipset not found"); -+ if (ipset->type != type && ~0 != ipset->type) -+ { -+ error = clib_error_return (0, "cannot change ipset type"); -+ goto done; -+ } -+ ipset->type = type; -+ -+ vec_foreach (member, members) -+ { -+ rv = capo_ipset_add_member (id, member); -+ if (rv) -+ error = clib_error_return (0, "capo_ipset_add_member error %d", rv); -+ } -+ -+done: -+ vec_free (members); -+ unformat_free (line_input); -+ return error; -+} -+ -+VLIB_CLI_COMMAND (capo_ipsets_add_member_cmd, static) = { -+ .path = "capo ipset add member", -+ .function = capo_ipsets_add_member_cmd_fn, -+ .short_help = "capo ipset add member [id] [prefix]", -+}; -+ -+static clib_error_t * -+capo_ipsets_del_member_cmd_fn (vlib_main_t *vm, unformat_input_t *input, -+ vlib_cli_command_t *cmd) -+{ -+ unformat_input_t _line_input, *line_input = &_line_input; -+ clib_error_t *error = 0; -+ u32 id = CAPO_INVALID_INDEX; -+ capo_ipset_type_t type; -+ capo_ipset_member_t tmp, *members = 0, *member; -+ capo_ipset_t *ipset; -+ int rv; -+ -+ if (!unformat_user (input, unformat_line_input, line_input)) -+ return clib_error_return (0, "missing parameters"); -+ -+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) -+ { -+ if (unformat (line_input, "id %u", &id)) -+ ; -+ else if (unformat (line_input, "%U", unformat_capo_ipset_member, &tmp, -+ &type)) -+ vec_add1 (members, tmp); -+ else -+ { -+ error = clib_error_return (0, "unknown input '%U'", -+ format_unformat_error, line_input); -+ goto done; -+ } -+ } -+ -+ if (CAPO_INVALID_INDEX == id) -+ { -+ error = clib_error_return (0, "missing ipset id"); -+ goto done; -+ } -+ -+ ipset = capo_ipsets_get_if_exists (id); -+ if (NULL == ipset) -+ return clib_error_return (0, "ipset not found"); -+ if (ipset->type != type) -+ { -+ error = clib_error_return (0, "wrong member type"); -+ goto done; -+ } -+ -+ vec_foreach (member, members) -+ { -+ rv = capo_ipset_del_member (id, member); -+ if (rv) -+ error = -+ clib_error_return (0, "capo_ipset_del_member errored with %d", rv); -+ } -+ -+done: -+ vec_free (members); -+ unformat_free (line_input); -+ return error; -+} -+ -+VLIB_CLI_COMMAND (capo_ipsets_del_member_cmd, static) = { -+ .path = "capo ipset del member", -+ .function = capo_ipsets_del_member_cmd_fn, -+ .short_help = "capo ipset del member [id] [prefix]", -+}; -+ -+/* -+ * fd.io coding-style-patch-verification: ON -+ * -+ * Local Variables: -+ * eval: (c-set-style "gnu") -+ * End: -+ */ -diff --git a/src/plugins/capo/capo_ipset.h b/src/plugins/capo/capo_ipset.h -new file mode 100644 -index 000000000..56bb0f466 ---- /dev/null -+++ b/src/plugins/capo/capo_ipset.h -@@ -0,0 +1,68 @@ -+/* -+ * Copyright (c) 2020 Cisco and/or its affiliates. -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at: -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+ * See the License for the specific language governing permissions and -+ * limitations under the License. -+ */ -+ -+#ifndef included_capo_ipset_h -+#define included_capo_ipset_h -+ -+#include -+ -+typedef enum -+{ -+ IPSET_TYPE_IP = 0, -+ IPSET_TYPE_IPPORT = 1, -+ IPSET_TYPE_NET = 2 -+} capo_ipset_type_t; -+ -+typedef struct -+{ -+ ip_address_t addr; -+ u16 port; -+ u8 l4proto; -+} capo_ipport_t; -+ -+typedef union -+{ -+ ip_address_t address; -+ capo_ipport_t ipport; -+ ip_prefix_t prefix; -+} capo_ipset_member_t; -+ -+typedef struct -+{ -+ capo_ipset_type_t type; -+ capo_ipset_member_t *members; -+} capo_ipset_t; -+ -+u32 capo_ipset_create (capo_ipset_type_t type); -+int capo_ipset_delete (u32 id); -+ -+int capo_ipset_add_member (u32 ipset_id, capo_ipset_member_t *member); -+int capo_ipset_del_member (u32 ipset_id, capo_ipset_member_t *member); -+ -+int capo_ipset_get_type (u32 id, capo_ipset_type_t *type); -+u8 *format_capo_ipset (u8 *s, va_list *args); -+capo_ipset_t *capo_ipsets_get_if_exists (u32 index); -+ -+extern capo_ipset_t *capo_ipsets; -+ -+#endif -+ -+/* -+ * fd.io coding-style-patch-verification: ON -+ * -+ * Local Variables: -+ * eval: (c-set-style "gnu") -+ * End: -+ */ -diff --git a/src/plugins/capo/capo_match.c b/src/plugins/capo/capo_match.c -new file mode 100644 -index 000000000..436151c1c ---- /dev/null -+++ b/src/plugins/capo/capo_match.c -@@ -0,0 +1,737 @@ -+/* -+ * Copyright (c) 2020 Cisco and/or its affiliates. -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at: -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+ * See the License for the specific language governing permissions and -+ * limitations under the License. -+ */ -+ -+#include -+ -+#include -+#include -+ -+/* for our bihash 8_32 */ -+#include -+ -+int -+capo_match_func (void *p_acl_main, u32 sw_if_index, u32 is_inbound, -+ fa_5tuple_opaque_t *opaque_5tuple, int is_ip6, u8 *r_action, -+ u32 *trace_bitmap) -+{ -+ fa_5tuple_t *pkt_5tuple = (fa_5tuple_t *) opaque_5tuple; -+ clib_bihash_kv_8_32_t conf_kv; -+ capo_interface_config_t *if_config; -+ capo_policy_t *policy; -+ u32 *policies; -+ int r; -+ u32 i; -+ -+ conf_kv.key = sw_if_index; -+ if (clib_bihash_search_8_32 (&capo_main.if_config, &conf_kv, &conf_kv) != 0) -+ { -+ /* no config for this interface found, allow */ -+ *r_action = 2; -+ return 0; -+ } -+ if_config = (capo_interface_config_t *) conf_kv.value; -+ policies = is_inbound ^ if_config->invert_rx_tx ? if_config->rx_policies : -+ if_config->tx_policies; -+ -+ if (vec_len (policies) == 0) -+ goto profiles; /* no policies, jump to profiles */ -+ -+ *r_action = 0; /* drop by default */ -+ -+ vec_foreach_index (i, policies) -+ { -+ policy = &capo_policies[policies[i]]; -+ r = capo_match_policy (policy, is_inbound ^ if_config->invert_rx_tx, -+ is_ip6, pkt_5tuple); -+ switch (r) -+ { -+ case CAPO_ALLOW: -+ *r_action = 2; /* allow */ -+ return 1; -+ case CAPO_DENY: -+ return 1; -+ case CAPO_PASS: -+ goto profiles; -+ case CAPO_LOG: -+ /* TODO: support LOG action */ -+ break; -+ default: -+ break; -+ } -+ }; -+ /* nothing matched, deny */ -+ return 1; -+ -+profiles: -+ if (vec_len (if_config->profiles) == 0) -+ { -+ *r_action = 2; /* no profiles, allow */ -+ return 1; -+ } -+ -+ vec_foreach_index (i, if_config->profiles) -+ { -+ policy = &capo_policies[if_config->profiles[i]]; -+ r = capo_match_policy (policy, is_inbound ^ if_config->invert_rx_tx, -+ is_ip6, pkt_5tuple); -+ switch (r) -+ { -+ case CAPO_ALLOW: -+ *r_action = 2; /* allow */ -+ return 1; -+ case CAPO_DENY: -+ return 1; -+ case CAPO_PASS: -+ clib_warning ("error: pass in profile %u", if_config->profiles[i]); -+ return 1; -+ case CAPO_LOG: -+ /* TODO: support LOG action */ -+ break; -+ default: -+ break; -+ } -+ }; -+ /* nothing matched, deny */ -+ return 1; -+} -+ -+int -+capo_match_policy (capo_policy_t *policy, u32 is_inbound, u32 is_ip6, -+ fa_5tuple_t *pkt_5tuple) -+{ -+ /* packets RX/TX from VPP perspective */ -+ u32 *rules = -+ is_inbound ? policy->rule_ids[VLIB_RX] : policy->rule_ids[VLIB_TX]; -+ u32 *rule_id; -+ capo_rule_t *rule; -+ int r; -+ -+ vec_foreach (rule_id, rules) -+ { -+ rule = &capo_rules[*rule_id]; -+ r = capo_match_rule (rule, is_ip6, pkt_5tuple); -+ if (r >= 0) -+ { -+ return r; -+ } -+ } -+ return -1; -+} -+ -+#define SRC 0 -+#define DST 1 -+ -+int -+capo_match_rule (capo_rule_t *rule, u32 is_ip6, fa_5tuple_t *pkt_5tuple) -+{ -+ // if (is_ip6 != (rule->af == AF_IP6)) { -+ // return -1; -+ // } -+ -+ ip4_address_t *src_ip4 = &pkt_5tuple->ip4_addr[SRC]; -+ ip4_address_t *dst_ip4 = &pkt_5tuple->ip4_addr[DST]; -+ ip6_address_t *src_ip6 = &pkt_5tuple->ip6_addr[SRC]; -+ ip6_address_t *dst_ip6 = &pkt_5tuple->ip6_addr[DST]; -+ u8 l4proto = pkt_5tuple->l4.proto; -+ u16 src_port = pkt_5tuple->l4.port[SRC]; -+ u16 dst_port = pkt_5tuple->l4.port[DST]; -+ u16 type = pkt_5tuple->l4.port[0]; -+ u16 code = pkt_5tuple->l4.port[1]; -+ -+ capo_rule_filter_t *filter; -+ vec_foreach (filter, rule->filters) -+ { -+ switch (filter->type) -+ { -+ case CAPO_RULE_FILTER_NONE_TYPE: -+ break; -+ case CAPO_RULE_FILTER_L4_PROTO: -+ if (filter->should_match && filter->value != l4proto) -+ return -1; -+ if (!filter->should_match && filter->value == l4proto) -+ return -2; -+ break; -+ case CAPO_RULE_FILTER_ICMP_TYPE: -+ if (l4proto == IP_PROTOCOL_ICMP || l4proto == IP_PROTOCOL_ICMP6) -+ { -+ if (filter->should_match && filter->value != type) -+ return -3; -+ if (!filter->should_match && filter->value == type) -+ return -4; -+ } -+ else -+ // A rule with an ICMP type / code specified doesn't match a -+ // non-icmp packet -+ return -5; -+ break; -+ case CAPO_RULE_FILTER_ICMP_CODE: -+ if (l4proto == IP_PROTOCOL_ICMP || l4proto == IP_PROTOCOL_ICMP6) -+ { -+ if (filter->should_match && filter->value != code) -+ return -6; -+ if (!filter->should_match && filter->value == code) -+ return -7; -+ } -+ else -+ // A rule with an ICMP type / code specified doesn't match a -+ // non-icmp packet -+ return -8; -+ break; -+ default: -+ // clib_warning ("unimplemented capo filter!"); -+ break; -+ } -+ } -+ -+ /* prefixes */ -+ if (rule->prefixes[CAPO_SRC]) -+ { -+ ip_prefix_t *prefix; -+ u8 found = 0; -+ vec_foreach (prefix, rule->prefixes[CAPO_SRC]) -+ { -+ u8 pfx_af = ip_prefix_version (prefix); -+ if (is_ip6 && pfx_af == AF_IP6) -+ { -+ if (ip6_destination_matches_route (&ip6_main, src_ip6, -+ &ip_addr_v6 (&prefix->addr), -+ prefix->len)) -+ { -+ found = 1; -+ break; -+ } -+ } -+ else if (!is_ip6 && pfx_af == AF_IP4) -+ { -+ if (ip4_destination_matches_route (&ip4_main, src_ip4, -+ &ip_addr_v4 (&prefix->addr), -+ prefix->len)) -+ { -+ found = 1; -+ break; -+ } -+ } -+ } -+ if (!found) -+ { -+ return -9; -+ } -+ } -+ -+ if (rule->prefixes[CAPO_NOT_SRC]) -+ { -+ ip_prefix_t *prefix; -+ vec_foreach (prefix, rule->prefixes[CAPO_NOT_SRC]) -+ { -+ u8 pfx_af = ip_prefix_version (prefix); -+ if (is_ip6 && pfx_af == AF_IP6) -+ { -+ if (ip6_destination_matches_route (&ip6_main, src_ip6, -+ &ip_addr_v6 (&prefix->addr), -+ prefix->len)) -+ { -+ return -10; -+ } -+ } -+ else if (!is_ip6 && pfx_af == AF_IP4) -+ { -+ if (ip4_destination_matches_route (&ip4_main, src_ip4, -+ &ip_addr_v4 (&prefix->addr), -+ prefix->len)) -+ { -+ return -11; -+ } -+ } -+ } -+ } -+ -+ if (rule->prefixes[CAPO_DST]) -+ { -+ ip_prefix_t *prefix; -+ u8 found = 0; -+ vec_foreach (prefix, rule->prefixes[CAPO_DST]) -+ { -+ u8 pfx_af = ip_prefix_version (prefix); -+ if (is_ip6 && pfx_af == AF_IP6) -+ { -+ if (ip6_destination_matches_route (&ip6_main, dst_ip6, -+ &ip_addr_v6 (&prefix->addr), -+ prefix->len)) -+ { -+ found = 1; -+ break; -+ } -+ } -+ else if (!is_ip6 && pfx_af == AF_IP4) -+ { -+ if (ip4_destination_matches_route (&ip4_main, dst_ip4, -+ &ip_addr_v4 (&prefix->addr), -+ prefix->len)) -+ { -+ found = 1; -+ break; -+ } -+ } -+ } -+ if (!found) -+ { -+ return -12; -+ } -+ } -+ -+ if (rule->prefixes[CAPO_NOT_DST]) -+ { -+ ip_prefix_t *prefix; -+ vec_foreach (prefix, rule->prefixes[CAPO_NOT_DST]) -+ { -+ u8 pfx_af = ip_prefix_version (prefix); -+ if (is_ip6 && pfx_af == AF_IP6) -+ { -+ if (ip6_destination_matches_route (&ip6_main, dst_ip6, -+ &ip_addr_v6 (&prefix->addr), -+ prefix->len)) -+ { -+ return -13; -+ } -+ } -+ else if (!is_ip6 && pfx_af == AF_IP4) -+ { -+ if (ip4_destination_matches_route (&ip4_main, dst_ip4, -+ &ip_addr_v4 (&prefix->addr), -+ prefix->len)) -+ { -+ return -14; -+ } -+ } -+ } -+ } -+ -+ /* IP ipsets */ -+ if (rule->ip_ipsets[CAPO_SRC]) -+ { -+ u32 *ipset; -+ u8 found = 0; -+ vec_foreach (ipset, rule->ip_ipsets[CAPO_SRC]) -+ { -+ if (is_ip6) -+ { -+ if (ipset_contains_ip6 (&capo_ipsets[*ipset], src_ip6)) -+ { -+ found = 1; -+ break; -+ } -+ } -+ else -+ { -+ if (ipset_contains_ip4 (&capo_ipsets[*ipset], src_ip4)) -+ { -+ found = 1; -+ break; -+ } -+ } -+ } -+ if (!found) -+ { -+ return -15; -+ } -+ } -+ -+ if (rule->ip_ipsets[CAPO_NOT_SRC]) -+ { -+ u32 *ipset; -+ vec_foreach (ipset, rule->ip_ipsets[CAPO_NOT_SRC]) -+ { -+ if (is_ip6) -+ { -+ if (ipset_contains_ip6 (&capo_ipsets[*ipset], src_ip6)) -+ { -+ return -16; -+ } -+ } -+ else -+ { -+ if (ipset_contains_ip4 (&capo_ipsets[*ipset], src_ip4)) -+ { -+ return -17; -+ } -+ } -+ } -+ } -+ -+ if (rule->ip_ipsets[CAPO_DST]) -+ { -+ u32 *ipset; -+ u8 found = 0; -+ vec_foreach (ipset, rule->ip_ipsets[CAPO_DST]) -+ { -+ if (is_ip6) -+ { -+ if (ipset_contains_ip6 (&capo_ipsets[*ipset], dst_ip6)) -+ { -+ found = 1; -+ break; -+ } -+ } -+ else -+ { -+ if (ipset_contains_ip4 (&capo_ipsets[*ipset], dst_ip4)) -+ { -+ found = 1; -+ break; -+ } -+ } -+ } -+ if (!found) -+ { -+ return -18; -+ } -+ } -+ -+ if (rule->ip_ipsets[CAPO_NOT_DST]) -+ { -+ u32 *ipset; -+ vec_foreach (ipset, rule->ip_ipsets[CAPO_NOT_DST]) -+ { -+ if (is_ip6) -+ { -+ if (ipset_contains_ip6 (&capo_ipsets[*ipset], dst_ip6)) -+ { -+ return -19; -+ } -+ } -+ else -+ { -+ if (ipset_contains_ip4 (&capo_ipsets[*ipset], dst_ip4)) -+ { -+ return -20; -+ } -+ } -+ } -+ } -+ -+ /* Special treatment for src / dst ports: they need to be in either the port -+ ranges or the port + ip ipsets / */ -+ u8 src_port_found = 0; -+ u8 dst_port_found = 0; -+ -+ /* port ranges */ -+ if (rule->port_ranges[CAPO_SRC]) -+ { -+ capo_port_range_t *range; -+ vec_foreach (range, rule->port_ranges[CAPO_SRC]) -+ { -+ if (range->start <= src_port && src_port <= range->end) -+ { -+ src_port_found = 1; -+ break; -+ } -+ } -+ } -+ -+ if (rule->port_ranges[CAPO_NOT_SRC]) -+ { -+ capo_port_range_t *range; -+ vec_foreach (range, rule->port_ranges[CAPO_NOT_SRC]) -+ { -+ if (range->start <= src_port && src_port <= range->end) -+ { -+ return -21; -+ } -+ } -+ } -+ -+ if (rule->port_ranges[CAPO_DST]) -+ { -+ capo_port_range_t *range; -+ vec_foreach (range, rule->port_ranges[CAPO_DST]) -+ { -+ if (range->start <= dst_port && dst_port <= range->end) -+ { -+ dst_port_found = 1; -+ break; -+ } -+ } -+ } -+ -+ if (rule->port_ranges[CAPO_NOT_DST]) -+ { -+ capo_port_range_t *range; -+ vec_foreach (range, rule->port_ranges[CAPO_NOT_DST]) -+ { -+ if (range->start <= dst_port && dst_port <= range->end) -+ { -+ return -22; -+ } -+ } -+ } -+ -+ /* ipport ipsets */ -+ if (rule->ipport_ipsets[CAPO_SRC]) -+ { -+ u32 *ipset; -+ vec_foreach (ipset, rule->ipport_ipsets[CAPO_SRC]) -+ { -+ if (is_ip6) -+ { -+ if (ipport_ipset_contains_ip6 (&capo_ipsets[*ipset], src_ip6, -+ l4proto, src_port)) -+ { -+ src_port_found = 1; -+ break; -+ } -+ } -+ else -+ { -+ if (ipport_ipset_contains_ip4 (&capo_ipsets[*ipset], src_ip4, -+ l4proto, src_port)) -+ { -+ src_port_found = 1; -+ break; -+ } -+ } -+ } -+ } -+ -+ if (rule->ipport_ipsets[CAPO_NOT_SRC]) -+ { -+ u32 *ipset; -+ vec_foreach (ipset, rule->ipport_ipsets[CAPO_NOT_SRC]) -+ { -+ if (is_ip6) -+ { -+ if (ipport_ipset_contains_ip6 (&capo_ipsets[*ipset], src_ip6, -+ l4proto, src_port)) -+ { -+ return -23; -+ } -+ } -+ else -+ { -+ if (ipport_ipset_contains_ip4 (&capo_ipsets[*ipset], src_ip4, -+ l4proto, src_port)) -+ { -+ return -24; -+ } -+ } -+ } -+ } -+ -+ if (rule->ipport_ipsets[CAPO_DST]) -+ { -+ u32 *ipset; -+ vec_foreach (ipset, rule->ipport_ipsets[CAPO_DST]) -+ { -+ if (is_ip6) -+ { -+ if (ipport_ipset_contains_ip6 (&capo_ipsets[*ipset], dst_ip6, -+ l4proto, dst_port)) -+ { -+ dst_port_found = 1; -+ break; -+ } -+ } -+ else -+ { -+ if (ipport_ipset_contains_ip4 (&capo_ipsets[*ipset], dst_ip4, -+ l4proto, dst_port)) -+ { -+ dst_port_found = 1; -+ break; -+ } -+ } -+ } -+ } -+ -+ if (rule->ipport_ipsets[CAPO_NOT_DST]) -+ { -+ u32 *ipset; -+ vec_foreach (ipset, rule->ipport_ipsets[CAPO_NOT_DST]) -+ { -+ if (is_ip6) -+ { -+ if (ipport_ipset_contains_ip6 (&capo_ipsets[*ipset], dst_ip6, -+ l4proto, dst_port)) -+ { -+ return -25; -+ } -+ } -+ else -+ { -+ if (ipport_ipset_contains_ip4 (&capo_ipsets[*ipset], dst_ip4, -+ l4proto, dst_port)) -+ { -+ return -26; -+ } -+ } -+ } -+ } -+ -+ if ((rule->port_ranges[CAPO_SRC] || rule->ipport_ipsets[CAPO_SRC]) && -+ (!src_port_found)) -+ { -+ return -27; -+ } -+ if ((rule->port_ranges[CAPO_DST] || rule->ipport_ipsets[CAPO_DST]) && -+ (!dst_port_found)) -+ { -+ return -28; -+ } -+ -+ return rule->action; -+} -+ -+u8 -+ip_ipset_contains_ip4 (capo_ipset_t *ipset, ip4_address_t *addr) -+{ -+ ASSERT (ipset->type == IPSET_TYPE_IP); -+ capo_ipset_member_t *member; -+ pool_foreach (member, ipset->members) -+ { -+ if (member->address.version != AF_IP4) -+ continue; -+ if (!ip4_address_compare (addr, &ip_addr_v4 (&member->address))) -+ return 1; -+ } -+ return 0; -+} -+ -+u8 -+ip_ipset_contains_ip6 (capo_ipset_t *ipset, ip6_address_t *addr) -+{ -+ ASSERT (ipset->type == IPSET_TYPE_IP); -+ capo_ipset_member_t *member; -+ pool_foreach (member, ipset->members) -+ { -+ if (member->address.version != AF_IP6) -+ continue; -+ if (!ip6_address_compare (addr, &ip_addr_v6 (&member->address))) -+ return 1; -+ } -+ return 0; -+} -+ -+u8 -+net_ipset_contains_ip4 (capo_ipset_t *ipset, ip4_address_t *addr) -+{ -+ ASSERT (ipset->type == IPSET_TYPE_NET); -+ capo_ipset_member_t *member; -+ pool_foreach (member, ipset->members) -+ { -+ if (member->prefix.addr.version != AF_IP4) -+ continue; -+ if (ip4_destination_matches_route (&ip4_main, addr, -+ &ip_addr_v4 (&member->prefix.addr), -+ member->prefix.len)) -+ { -+ return 1; -+ } -+ } -+ return 0; -+} -+ -+u8 -+net_ipset_contains_ip6 (capo_ipset_t *ipset, ip6_address_t *addr) -+{ -+ ASSERT (ipset->type == IPSET_TYPE_NET); -+ capo_ipset_member_t *member; -+ pool_foreach (member, ipset->members) -+ { -+ if (member->prefix.addr.version != AF_IP6) -+ continue; -+ if (ip6_destination_matches_route (&ip6_main, addr, -+ &ip_addr_v6 (&member->prefix.addr), -+ member->prefix.len)) -+ { -+ return 1; -+ } -+ } -+ return 0; -+} -+ -+u8 -+ipset_contains_ip4 (capo_ipset_t *ipset, ip4_address_t *addr) -+{ -+ switch (ipset->type) -+ { -+ case IPSET_TYPE_IP: -+ return ip_ipset_contains_ip4 (ipset, addr); -+ case IPSET_TYPE_NET: -+ return net_ipset_contains_ip4 (ipset, addr); -+ default: -+ clib_warning ("Wrong ipset type"); -+ } -+ return 0; -+} -+ -+u8 -+ipset_contains_ip6 (capo_ipset_t *ipset, ip6_address_t *addr) -+{ -+ switch (ipset->type) -+ { -+ case IPSET_TYPE_IP: -+ return ip_ipset_contains_ip6 (ipset, addr); -+ case IPSET_TYPE_NET: -+ return net_ipset_contains_ip6 (ipset, addr); -+ default: -+ clib_warning ("Wrong ipset type"); -+ } -+ return 0; -+} -+ -+u8 -+ipport_ipset_contains_ip4 (capo_ipset_t *ipset, ip4_address_t *addr, -+ u8 l4proto, u16 port) -+{ -+ ASSERT (ipset->type == IPSET_TYPE_IPPORT); -+ capo_ipset_member_t *member; -+ pool_foreach (member, ipset->members) -+ { -+ if (member->ipport.addr.version != AF_IP4) -+ continue; -+ if (l4proto == member->ipport.l4proto && port == member->ipport.port && -+ !ip4_address_compare (addr, &ip_addr_v4 (&member->ipport.addr))) -+ { -+ return 1; -+ } -+ } -+ return 0; -+} -+ -+u8 -+ipport_ipset_contains_ip6 (capo_ipset_t *ipset, ip6_address_t *addr, -+ u8 l4proto, u16 port) -+{ -+ ASSERT (ipset->type == IPSET_TYPE_IPPORT); -+ capo_ipset_member_t *member; -+ pool_foreach (member, ipset->members) -+ { -+ if (member->ipport.addr.version != AF_IP6) -+ continue; -+ if (l4proto == member->ipport.l4proto && port == member->ipport.port && -+ !ip6_address_compare (addr, &ip_addr_v6 (&member->ipport.addr))) -+ { -+ return 1; -+ } -+ } -+ return 0; -+} -+ -+/* -+ * fd.io coding-style-patch-verification: ON -+ * -+ * Local Variables: -+ * eval: (c-set-style "gnu") -+ * End: -+ */ -diff --git a/src/plugins/capo/capo_match.h b/src/plugins/capo/capo_match.h -new file mode 100644 -index 000000000..fe1907485 ---- /dev/null -+++ b/src/plugins/capo/capo_match.h -@@ -0,0 +1,49 @@ -+/* -+ * Copyright (c) 2020 Cisco and/or its affiliates. -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at: -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+ * See the License for the specific language governing permissions and -+ * limitations under the License. -+ */ -+ -+#ifndef included_capo_match_h -+#define included_capo_match_h -+ -+#include -+#include -+ -+#include -+#include -+#include -+ -+int capo_match_func (void *p_acl_main, u32 sw_if_index, u32 is_inbound, -+ fa_5tuple_opaque_t *opaque_5tuple, int is_ip6, -+ u8 *r_action, u32 *trace_bitmap); -+ -+int capo_match_policy (capo_policy_t *policy, u32 is_inbound, u32 is_ip6, -+ fa_5tuple_t *pkt_5tuple); -+int capo_match_rule (capo_rule_t *rule, u32 is_ip6, fa_5tuple_t *pkt_5tuple); -+ -+u8 ipset_contains_ip4 (capo_ipset_t *ipset, ip4_address_t *addr); -+u8 ipset_contains_ip6 (capo_ipset_t *ipset, ip6_address_t *addr); -+u8 ipport_ipset_contains_ip4 (capo_ipset_t *ipset, ip4_address_t *addr, -+ u8 l4proto, u16 port); -+u8 ipport_ipset_contains_ip6 (capo_ipset_t *ipset, ip6_address_t *addr, -+ u8 l4proto, u16 port); -+ -+#endif -+ -+/* -+ * fd.io coding-style-patch-verification: ON -+ * -+ * Local Variables: -+ * eval: (c-set-style "gnu") -+ * End: -+ */ -diff --git a/src/plugins/capo/capo_policy.c b/src/plugins/capo/capo_policy.c -new file mode 100644 -index 000000000..d6e8992b7 ---- /dev/null -+++ b/src/plugins/capo/capo_policy.c -@@ -0,0 +1,265 @@ -+/* -+ * Copyright (c) 2020 Cisco and/or its affiliates. -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at: -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+ * See the License for the specific language governing permissions and -+ * limitations under the License. -+ */ -+ -+#include -+#include -+#include -+ -+capo_policy_t *capo_policies; -+ -+static capo_policy_t * -+capo_policy_alloc () -+{ -+ capo_policy_t *policy; -+ pool_get_zero (capo_policies, policy); -+ return policy; -+} -+ -+capo_policy_t * -+capo_policy_get_if_exists (u32 index) -+{ -+ if (pool_is_free_index (capo_policies, index)) -+ return (NULL); -+ return pool_elt_at_index (capo_policies, index); -+} -+ -+static void -+capo_policy_cleanup (capo_policy_t *policy) -+{ -+ for (int i = 0; i < VLIB_N_RX_TX; i++) -+ vec_free (policy->rule_ids[i]); -+} -+ -+int -+capo_policy_update (u32 *id, capo_policy_rule_t *rules) -+{ -+ capo_policy_t *policy; -+ capo_policy_rule_t *rule; -+ -+ policy = capo_policy_get_if_exists (*id); -+ if (policy) -+ capo_policy_cleanup (policy); -+ else -+ policy = capo_policy_alloc (); -+ -+ vec_foreach (rule, rules) -+ vec_add1 (policy->rule_ids[rule->direction], rule->rule_id); -+ -+ *id = policy - capo_policies; -+ return 0; -+} -+ -+int -+capo_policy_delete (u32 id) -+{ -+ capo_policy_t *policy; -+ policy = capo_policy_get_if_exists (id); -+ if (NULL == policy) -+ return VNET_API_ERROR_NO_SUCH_ENTRY; -+ -+ capo_policy_cleanup (policy); -+ pool_put (capo_policies, policy); -+ -+ return 0; -+} -+ -+u8 * -+format_capo_policy (u8 *s, va_list *args) -+{ -+ capo_policy_t *policy = va_arg (*args, capo_policy_t *); -+ int indent = va_arg (*args, int); -+ int verbose = va_arg (*args, int); -+ int invert_rx_tx = va_arg (*args, int); -+ u32 *rule_id; -+ -+ if (policy == NULL) -+ return format (s, "deleted policy"); -+ -+ if (verbose) -+ { -+ s = format (s, "[policy#%u]\n", policy - capo_policies); -+ capo_rule_t *rule; -+ if (verbose != CAPO_POLICY_ONLY_RX) -+ vec_foreach (rule_id, policy->rule_ids[VLIB_TX ^ invert_rx_tx]) -+ { -+ rule = capo_rule_get_if_exists (*rule_id); -+ s = format (s, "%Utx:%U\n", format_white_space, indent + 2, -+ format_capo_rule, rule); -+ } -+ if (verbose != CAPO_POLICY_ONLY_TX) -+ vec_foreach (rule_id, policy->rule_ids[VLIB_RX ^ invert_rx_tx]) -+ { -+ rule = capo_rule_get_if_exists (*rule_id); -+ s = format (s, "%Urx:%U\n", format_white_space, indent + 2, -+ format_capo_rule, rule); -+ } -+ } -+ else -+ { -+ s = format (s, "[policy#%u] rx-rules:%d tx-rules:%d\n", -+ policy - capo_policies, -+ vec_len (policy->rule_ids[VLIB_RX ^ invert_rx_tx]), -+ vec_len (policy->rule_ids[VLIB_TX ^ invert_rx_tx])); -+ } -+ -+ return (s); -+} -+ -+static clib_error_t * -+capo_policies_show_cmd_fn (vlib_main_t *vm, unformat_input_t *input, -+ vlib_cli_command_t *cmd) -+{ -+ unformat_input_t _line_input, *line_input = &_line_input; -+ clib_error_t *error = 0; -+ capo_policy_t *policy; -+ u8 verbose = 0, has_input = 0; -+ -+ if (unformat_user (input, unformat_line_input, line_input)) -+ { -+ has_input = 1; -+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) -+ { -+ if (unformat (line_input, "verbose")) -+ verbose = 1; -+ else -+ { -+ error = clib_error_return (0, "unknown input '%U'", -+ format_unformat_error, line_input); -+ goto done; -+ } -+ } -+ } -+ -+ pool_foreach (policy, capo_policies) -+ vlib_cli_output (vm, "%U", format_capo_policy, policy, 0, /* indent */ -+ verbose, 0 /* invert_rx_tx */); -+ -+done: -+ if (has_input) -+ unformat_free (line_input); -+ return error; -+} -+ -+VLIB_CLI_COMMAND (capo_policies_show_cmd, static) = { -+ .path = "show capo policies", -+ .function = capo_policies_show_cmd_fn, -+ .short_help = "show capo policies [verbose]", -+}; -+ -+static clib_error_t * -+capo_policies_add_cmd_fn (vlib_main_t *vm, unformat_input_t *input, -+ vlib_cli_command_t *cmd) -+{ -+ unformat_input_t _line_input, *line_input = &_line_input; -+ clib_error_t *error = 0; -+ u32 id = CAPO_INVALID_INDEX, rule_id; -+ capo_policy_rule_t *policy_rules = 0, *policy_rule; -+ int direction = VLIB_RX; -+ int rv; -+ -+ if (!unformat_user (input, unformat_line_input, line_input)) -+ return clib_error_return (0, "missing parameters"); -+ -+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) -+ { -+ if (unformat (line_input, "update %u", &id)) -+ ; -+ else if (unformat (line_input, "%U", unformat_vlib_rx_tx, &direction)) -+ ; -+ else if (unformat (line_input, "%u", &rule_id)) -+ { -+ vec_add2 (policy_rules, policy_rule, 1); -+ policy_rule->rule_id = rule_id; -+ policy_rule->direction = direction; -+ } -+ else -+ { -+ error = clib_error_return (0, "unknown input '%U'", -+ format_unformat_error, line_input); -+ goto done; -+ } -+ } -+ -+ rv = capo_policy_update (&id, policy_rules); -+ if (rv) -+ error = clib_error_return (0, "capo_policy_delete errored with %d", rv); -+ else -+ vlib_cli_output (vm, "capo policy %d added", id); -+ -+done: -+ vec_free (policy_rules); -+ unformat_free (line_input); -+ return error; -+} -+ -+VLIB_CLI_COMMAND (capo_policies_add_cmd, static) = { -+ .path = "capo policy add", -+ .function = capo_policies_add_cmd_fn, -+ .short_help = "capo policy add [rx rule_id rule_id ...] [tx rule_id rule_id " -+ "...] [update [id]]", -+}; -+ -+static clib_error_t * -+capo_policies_del_cmd_fn (vlib_main_t *vm, unformat_input_t *input, -+ vlib_cli_command_t *cmd) -+{ -+ unformat_input_t _line_input, *line_input = &_line_input; -+ clib_error_t *error = 0; -+ u32 id = CAPO_INVALID_INDEX; -+ int rv; -+ -+ if (!unformat_user (input, unformat_line_input, line_input)) -+ return clib_error_return (0, "missing policy id"); -+ -+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) -+ { -+ if (unformat (line_input, "%u", &id)) -+ ; -+ else -+ { -+ error = clib_error_return (0, "unknown input '%U'", -+ format_unformat_error, line_input); -+ goto done; -+ } -+ } -+ -+ if (CAPO_INVALID_INDEX == id) -+ { -+ error = clib_error_return (0, "missing policy id"); -+ goto done; -+ } -+ -+ rv = capo_policy_delete (id); -+ if (rv) -+ error = clib_error_return (0, "capo_policy_delete errored with %d", rv); -+ -+done: -+ unformat_free (line_input); -+ return error; -+} -+ -+VLIB_CLI_COMMAND (capo_policies_del_cmd, static) = { -+ .path = "capo policy del", -+ .function = capo_policies_del_cmd_fn, -+ .short_help = "capo policy del [id]", -+}; -+ -+/* -+ * fd.io coding-style-patch-verification: ON -+ * -+ * Local Variables: -+ * eval: (c-set-style "gnu") -+ * End: -+ */ -diff --git a/src/plugins/capo/capo_policy.h b/src/plugins/capo/capo_policy.h -new file mode 100644 -index 000000000..c598f9ade ---- /dev/null -+++ b/src/plugins/capo/capo_policy.h -@@ -0,0 +1,58 @@ -+/* -+ * Copyright (c) 2020 Cisco and/or its affiliates. -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at: -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+ * See the License for the specific language governing permissions and -+ * limitations under the License. -+ */ -+ -+#ifndef included_capo_policy_h -+#define included_capo_policy_h -+ -+#include -+ -+typedef struct -+{ -+ /* VLIB_RX for inbound -+ VLIB_TX for outbound */ -+ u32 *rule_ids[VLIB_N_RX_TX]; -+} capo_policy_t; -+ -+typedef struct -+{ -+ u32 rule_id; -+ /* VLIB_RX or VLIB_TX */ -+ u8 direction; -+} capo_policy_rule_t; -+ -+typedef enum -+{ -+ CAPO_POLICY_QUIET, -+ CAPO_POLICY_VERBOSE, -+ CAPO_POLICY_ONLY_RX, -+ CAPO_POLICY_ONLY_TX, -+} capo_policy_format_type_t; -+ -+extern capo_policy_t *capo_policies; -+ -+int capo_policy_update (u32 *id, capo_policy_rule_t *rules); -+int capo_policy_delete (u32 id); -+u8 *format_capo_policy (u8 *s, va_list *args); -+capo_policy_t *capo_policy_get_if_exists (u32 index); -+ -+#endif -+ -+/* -+ * fd.io coding-style-patch-verification: ON -+ * -+ * Local Variables: -+ * eval: (c-set-style "gnu") -+ * End: -+ */ -diff --git a/src/plugins/capo/capo_rule.c b/src/plugins/capo/capo_rule.c -new file mode 100644 -index 000000000..c672f29bd ---- /dev/null -+++ b/src/plugins/capo/capo_rule.c -@@ -0,0 +1,509 @@ -+/* -+ * Copyright (c) 2020 Cisco and/or its affiliates. -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at: -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+ * See the License for the specific language governing permissions and -+ * limitations under the License. -+ */ -+ -+#include -+#include -+#include -+ -+capo_rule_t *capo_rules; -+ -+u8 * -+format_capo_rule_action (u8 *s, va_list *args) -+{ -+ capo_rule_action_t action = va_arg (*args, int); -+ switch (action) -+ { -+ case CAPO_ALLOW: -+ return format (s, "allow"); -+ case CAPO_DENY: -+ return format (s, "deny"); -+ case CAPO_LOG: -+ return format (s, "log"); -+ case CAPO_PASS: -+ return format (s, "pass"); -+ default: -+ return format (s, "unknownaction"); -+ } -+} -+ -+uword -+unformat_capo_rule_action (unformat_input_t *input, va_list *args) -+{ -+ capo_rule_action_t *action = va_arg (*args, capo_rule_action_t *); -+ if (unformat (input, "allow")) -+ *action = CAPO_ALLOW; -+ else if (unformat (input, "deny")) -+ *action = CAPO_DENY; -+ else if (unformat (input, "log")) -+ *action = CAPO_LOG; -+ else if (unformat (input, "pass")) -+ *action = CAPO_PASS; -+ else -+ return 0; -+ return 1; -+} -+ -+u8 * -+format_capo_rule_port_range (u8 *s, va_list *args) -+{ -+ capo_port_range_t *port_range = va_arg (*args, capo_port_range_t *); -+ -+ if (port_range->start != port_range->end) -+ s = format (s, "[%u-%u]", port_range->start, port_range->end); -+ else -+ s = format (s, "%u", port_range->start); -+ -+ return (s); -+} -+ -+u8 * -+format_capo_rule_entry (u8 *s, va_list *args) -+{ -+ capo_rule_entry_t *entry = va_arg (*args, capo_rule_entry_t *); -+ capo_ipset_t *ipset; -+ -+ s = format (s, "%s", entry->flags & CAPO_IS_SRC ? "src" : "dst"); -+ s = format (s, "%s", entry->flags & CAPO_IS_NOT ? "!=" : "=="); -+ switch (entry->type) -+ { -+ case CAPO_CIDR: -+ s = format (s, "%U", format_ip_prefix, &entry->data.cidr); -+ break; -+ case CAPO_PORT_RANGE: -+ s = -+ format (s, "%U", format_capo_rule_port_range, &entry->data.port_range); -+ break; -+ case CAPO_IP_SET: -+ ipset = capo_ipsets_get_if_exists (entry->data.set_id); -+ s = format (s, "%U", format_capo_ipset, ipset); -+ break; -+ case CAPO_PORT_IP_SET: -+ ipset = capo_ipsets_get_if_exists (entry->data.set_id); -+ s = format (s, "%U", format_capo_ipset, ipset); -+ break; -+ default: -+ s = format (s, "unknown"); -+ break; -+ } -+ return (s); -+} -+ -+uword -+unformat_rule_key_flag (unformat_input_t *input, va_list *args) -+{ -+ capo_rule_key_flag_t *flags = va_arg (*args, capo_rule_key_flag_t *); -+ if (unformat (input, "src==")) -+ *flags = CAPO_IS_SRC; -+ else if (unformat (input, "src!=")) -+ *flags = CAPO_IS_SRC | CAPO_IS_NOT; -+ else if (unformat (input, "dst!=")) -+ *flags = CAPO_IS_NOT; -+ else if (unformat (input, "dst==")) -+ *flags = 0; -+ else -+ return 0; -+ return 1; -+} -+ -+uword -+unformat_capo_port_range (unformat_input_t *input, va_list *args) -+{ -+ capo_port_range_t *port_range = va_arg (*args, capo_port_range_t *); -+ u32 start, end; -+ if (unformat (input, "[%d-%d]", &start, &end)) -+ { -+ port_range->start = (u16) start; -+ port_range->end = (u16) end; -+ } -+ else -+ return 0; -+ return 1; -+} -+ -+uword -+unformat_capo_rule_entry (unformat_input_t *input, va_list *args) -+{ -+ capo_rule_entry_t *entry = va_arg (*args, capo_rule_entry_t *); -+ if (unformat (input, "%U %U", unformat_rule_key_flag, &entry->flags, -+ unformat_ip_prefix, &entry->data.cidr)) -+ entry->type = CAPO_CIDR; -+ else if (unformat (input, "%U %U", unformat_rule_key_flag, &entry->flags, -+ unformat_capo_port_range, &entry->data.port_range)) -+ entry->type = CAPO_PORT_RANGE; -+ else if (unformat (input, "%Uset %u", unformat_rule_key_flag, &entry->flags, -+ &entry->data.set_id)) -+ entry->type = CAPO_PORT_IP_SET; -+ else -+ return 0; -+ return 1; -+} -+ -+u8 * -+format_capo_rule_filter (u8 *s, va_list *args) -+{ -+ capo_rule_filter_t *filter = va_arg (*args, capo_rule_filter_t *); -+ switch (filter->type) -+ { -+ case CAPO_RULE_FILTER_NONE_TYPE: -+ return format (s, ""); -+ case CAPO_RULE_FILTER_ICMP_TYPE: -+ return format (s, "icmp-type%s=%d", filter->should_match ? "=" : "!", -+ filter->value); -+ case CAPO_RULE_FILTER_ICMP_CODE: -+ return format (s, "icmp-code%s=%d", filter->should_match ? "=" : "!", -+ filter->value); -+ case CAPO_RULE_FILTER_L4_PROTO: -+ return format (s, "proto%s=%U", filter->should_match ? "=" : "!", -+ format_ip_protocol, filter->value); -+ default: -+ return format (s, "unknown"); -+ } -+} -+ -+uword -+unformat_capo_should_match (unformat_input_t *input, va_list *args) -+{ -+ u8 *should_match = va_arg (*args, u8 *); -+ if (unformat (input, "==")) -+ *should_match = 1; -+ else if (unformat (input, "!=")) -+ *should_match = 0; -+ else -+ return 0; -+ return 1; -+} -+ -+uword -+unformat_capo_rule_filter (unformat_input_t *input, va_list *args) -+{ -+ u8 tmp_value; -+ capo_rule_filter_t *filter = va_arg (*args, capo_rule_filter_t *); -+ if (unformat (input, "icmp-type%U%d", unformat_capo_should_match, -+ &filter->should_match, &filter->value)) -+ filter->type = CAPO_RULE_FILTER_ICMP_TYPE; -+ else if (unformat (input, "icmp-code%U%d", unformat_capo_should_match, -+ &filter->should_match, &filter->value)) -+ filter->type = CAPO_RULE_FILTER_ICMP_CODE; -+ else if (unformat (input, "proto%U%U", unformat_capo_should_match, -+ &filter->should_match, unformat_ip_protocol, &tmp_value)) -+ { -+ filter->value = tmp_value; -+ filter->type = CAPO_RULE_FILTER_L4_PROTO; -+ } -+ else -+ return 0; -+ return 1; -+} -+ -+static capo_rule_entry_t * -+capo_rule_get_entries (capo_rule_t *rule) -+{ -+ capo_rule_entry_t *entries = NULL, *entry; -+ capo_port_range_t *pr; -+ ip_prefix_t *pfx; -+ u32 *set_id; -+ for (int i = 0; i < CAPO_RULE_MAX_FLAGS; i++) -+ { -+ vec_foreach (pfx, rule->prefixes[i]) -+ { -+ vec_add2 (entries, entry, 1); -+ entry->type = CAPO_CIDR; -+ entry->flags = i; -+ clib_memcpy (&entry->data.cidr, pfx, sizeof (*pfx)); -+ } -+ vec_foreach (pr, rule->port_ranges[i]) -+ { -+ vec_add2 (entries, entry, 1); -+ entry->type = CAPO_PORT_RANGE; -+ entry->flags = i; -+ clib_memcpy (&entry->data.port_range, pr, sizeof (*pr)); -+ } -+ vec_foreach (set_id, rule->ip_ipsets[i]) -+ { -+ vec_add2 (entries, entry, 1); -+ entry->type = CAPO_IP_SET; -+ entry->flags = i; -+ entry->data.set_id = *set_id; -+ } -+ vec_foreach (set_id, rule->ipport_ipsets[i]) -+ { -+ vec_add2 (entries, entry, 1); -+ entry->type = CAPO_PORT_IP_SET; -+ entry->flags = i; -+ entry->data.set_id = *set_id; -+ } -+ } -+ return entries; -+} -+ -+u8 * -+format_capo_rule (u8 *s, va_list *args) -+{ -+ capo_rule_t *rule = va_arg (*args, capo_rule_t *); -+ capo_rule_filter_t *filter; -+ capo_rule_entry_t *entry, *entries; -+ -+ if (rule == NULL) -+ return format (s, "deleted rule"); -+ -+ s = format (s, "[rule#%d;%U][", rule - capo_rules, format_capo_rule_action, -+ rule->action); -+ -+ /* filters */ -+ vec_foreach (filter, rule->filters) -+ { -+ if (filter->type != CAPO_RULE_FILTER_NONE_TYPE) -+ s = format (s, "%U,", format_capo_rule_filter, filter); -+ } -+ -+ entries = capo_rule_get_entries (rule); -+ vec_foreach (entry, entries) -+ s = format (s, "%U,", format_capo_rule_entry, entry); -+ vec_free (entries); -+ s = format (s, "]"); -+ -+ return (s); -+} -+ -+capo_rule_t * -+capo_rule_alloc () -+{ -+ capo_rule_t *rule; -+ pool_get_zero (capo_rules, rule); -+ return rule; -+} -+ -+capo_rule_t * -+capo_rule_get_if_exists (u32 index) -+{ -+ if (pool_is_free_index (capo_rules, index)) -+ return (NULL); -+ return pool_elt_at_index (capo_rules, index); -+} -+ -+static void -+capo_rule_cleanup (capo_rule_t *rule) -+{ -+ int i; -+ vec_free (rule->filters); -+ for (i = 0; i < CAPO_RULE_MAX_FLAGS; i++) -+ { -+ vec_free (rule->prefixes[i]); -+ vec_free (rule->port_ranges[i]); -+ vec_free (rule->ip_ipsets[i]); -+ vec_free (rule->ipport_ipsets[i]); -+ } -+} -+ -+int -+capo_rule_update (u32 *id, capo_rule_action_t action, ip_address_family_t af, -+ capo_rule_filter_t *filters, capo_rule_entry_t *entries) -+{ -+ capo_rule_filter_t *filter; -+ capo_rule_entry_t *entry; -+ capo_rule_t *rule; -+ int rv; -+ -+ rule = capo_rule_get_if_exists (*id); -+ if (rule) -+ capo_rule_cleanup (rule); -+ else -+ rule = capo_rule_alloc (); -+ -+ rule->af = -1; -+ rule->action = action; -+ vec_foreach (filter, filters) -+ vec_add1 (rule->filters, *filter); -+ -+ vec_foreach (entry, entries) -+ { -+ u8 flags = entry->flags; -+ switch (entry->type) -+ { -+ case CAPO_CIDR: -+ vec_add1 (rule->prefixes[flags], entry->data.cidr); -+ break; -+ case CAPO_PORT_RANGE: -+ vec_add1 (rule->port_ranges[flags], entry->data.port_range); -+ break; -+ case CAPO_PORT_IP_SET: -+ vec_add1 (rule->ipport_ipsets[flags], entry->data.set_id); -+ break; -+ case CAPO_IP_SET: -+ vec_add1 (rule->ip_ipsets[flags], entry->data.set_id); -+ break; -+ default: -+ rv = 1; -+ goto error; -+ } -+ } -+ *id = rule - capo_rules; -+ return 0; -+error: -+ capo_rule_cleanup (rule); -+ pool_put (capo_rules, rule); -+ return rv; -+} -+ -+int -+capo_rule_delete (u32 id) -+{ -+ capo_rule_t *rule; -+ rule = capo_rule_get_if_exists (id); -+ if (NULL == rule) -+ return VNET_API_ERROR_NO_SUCH_ENTRY; -+ -+ capo_rule_cleanup (rule); -+ pool_put (capo_rules, rule); -+ -+ return 0; -+} -+ -+static clib_error_t * -+capo_rules_show_cmd_fn (vlib_main_t *vm, unformat_input_t *input, -+ vlib_cli_command_t *cmd) -+{ -+ capo_rule_t *rule; -+ -+ pool_foreach (rule, capo_rules) -+ { -+ vlib_cli_output (vm, "%U", format_capo_rule, rule); -+ } -+ -+ return 0; -+} -+ -+VLIB_CLI_COMMAND (capo_rules_show_cmd, static) = { -+ .path = "show capo rules", -+ .function = capo_rules_show_cmd_fn, -+ .short_help = "show capo rules", -+}; -+ -+static clib_error_t * -+capo_rules_add_cmd_fn (vlib_main_t *vm, unformat_input_t *input, -+ vlib_cli_command_t *cmd) -+{ -+ unformat_input_t _line_input, *line_input = &_line_input; -+ capo_rule_filter_t tmp_filter, *filters = 0; -+ capo_rule_entry_t tmp_entry, *entries = 0; -+ clib_error_t *error = 0; -+ capo_rule_action_t action; -+ ip_address_family_t af = AF_IP4; -+ u32 id = CAPO_INVALID_INDEX; -+ int rv; -+ -+ if (!unformat_user (input, unformat_line_input, line_input)) -+ return 0; -+ -+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) -+ { -+ if (unformat (line_input, "update %u", &id)) -+ ; -+ else if (unformat_user (line_input, unformat_ip_address_family, &af)) -+ ; -+ else if (unformat_user (line_input, unformat_capo_rule_action, &action)) -+ ; -+ else if (unformat_user (line_input, unformat_capo_rule_entry, -+ &tmp_entry)) -+ vec_add1 (entries, tmp_entry); -+ else if (unformat_user (line_input, unformat_capo_rule_filter, -+ &tmp_filter)) -+ { -+ vec_add1 (filters, tmp_filter); -+ vlib_cli_output (vm, "%U", format_capo_rule_filter, &tmp_filter); -+ } -+ else -+ { -+ error = clib_error_return (0, "unknown input '%U'", -+ format_unformat_error, line_input); -+ goto done; -+ } -+ } -+ -+ rv = capo_rule_update (&id, action, af, filters, entries); -+ if (rv) -+ error = clib_error_return (0, "capo_rule_update error %d", rv); -+ else -+ vlib_cli_output (vm, "capo rule %d added", id); -+ -+done: -+ vec_free (filters); -+ vec_free (entries); -+ unformat_free (line_input); -+ return error; -+} -+ -+VLIB_CLI_COMMAND (capo_rules_add_cmd, static) = { -+ .path = "capo rule add", -+ .function = capo_rules_add_cmd_fn, -+ .short_help = "capo rule add [ip4|ip6] [allow|deny|log|pass]" -+ "[filter[==|!=]value]" -+ "[[src|dst][==|!=][prefix|set ID|[port-port]]]", -+ .long_help = "Add a rule, with given filters and entries\n" -+ "filters can be `icmp-type`, `icmp-code` and `proto`", -+}; -+ -+static clib_error_t * -+capo_rules_del_cmd_fn (vlib_main_t *vm, unformat_input_t *input, -+ vlib_cli_command_t *cmd) -+{ -+ unformat_input_t _line_input, *line_input = &_line_input; -+ clib_error_t *error = 0; -+ u32 id = CAPO_INVALID_INDEX; -+ int rv; -+ -+ if (!unformat_user (input, unformat_line_input, line_input)) -+ return clib_error_return (0, "missing rule id"); -+ -+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) -+ { -+ if (unformat (line_input, "%u", &id)) -+ ; -+ else -+ { -+ error = clib_error_return (0, "unknown input '%U'", -+ format_unformat_error, line_input); -+ goto done; -+ } -+ } -+ -+ if (CAPO_INVALID_INDEX == id) -+ { -+ error = clib_error_return (0, "missing rule id"); -+ goto done; -+ } -+ -+ rv = capo_rule_delete (id); -+ if (rv) -+ error = clib_error_return (0, "capo_rule_delete errored with %d", rv); -+ -+done: -+ unformat_free (line_input); -+ return error; -+} -+ -+VLIB_CLI_COMMAND (capo_rules_del_cmd, static) = { -+ .path = "capo rule del", -+ .function = capo_rules_del_cmd_fn, -+ .short_help = "capo rule del [id]", -+}; -+ -+/* -+ * fd.io coding-style-patch-verification: ON -+ * -+ * Local Variables: -+ * eval: (c-set-style "gnu") -+ * End: -+ */ -diff --git a/src/plugins/capo/capo_rule.h b/src/plugins/capo/capo_rule.h -new file mode 100644 -index 000000000..0875a45c5 ---- /dev/null -+++ b/src/plugins/capo/capo_rule.h -@@ -0,0 +1,91 @@ -+/* -+ * Copyright (c) 2020 Cisco and/or its affiliates. -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at: -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+ * See the License for the specific language governing permissions and -+ * limitations under the License. -+ */ -+ -+#ifndef included_capo_rule_h -+#define included_capo_rule_h -+ -+#include -+ -+typedef vl_api_capo_rule_action_t capo_rule_action_t; -+typedef vl_api_capo_entry_type_t capo_entry_type_t; -+typedef vl_api_capo_rule_filter_type_t capo_rule_filter_type_t; -+ -+typedef struct capo_rule_filter_ -+{ -+ capo_rule_filter_type_t type; -+ /* Content to filter against */ -+ u32 value; -+ /* If true match packet.property == opaque, else packet.property != opaque */ -+ u8 should_match; -+} capo_rule_filter_t; -+ -+typedef union capo_entry_data_t_ -+{ -+ ip_prefix_t cidr; -+ capo_port_range_t port_range; -+ u32 set_id; -+} capo_entry_data_t; -+ -+typedef enum capo_rule_key_flag_ -+{ -+ CAPO_IS_SRC = 1 << 0, -+ CAPO_IS_NOT = 1 << 1, -+ CAPO_RULE_MAX_FLAGS = 1 << 2, -+} capo_rule_key_flag_t; -+ -+#define CAPO_SRC CAPO_IS_SRC -+#define CAPO_NOT_SRC (CAPO_IS_SRC | CAPO_IS_NOT) -+#define CAPO_DST 0 -+#define CAPO_NOT_DST CAPO_IS_NOT -+ -+typedef struct capo_rule_entry_t_ -+{ -+ capo_entry_type_t type; -+ capo_entry_data_t data; -+ capo_rule_key_flag_t flags; -+} capo_rule_entry_t; -+ -+typedef struct capo_rule_ -+{ -+ ip_address_family_t af; -+ capo_rule_action_t action; -+ -+ capo_rule_filter_t *filters; -+ -+ /* Indexed by capo_rule_key_flag_t */ -+ ip_prefix_t *prefixes[CAPO_RULE_MAX_FLAGS]; -+ u32 *ip_ipsets[CAPO_RULE_MAX_FLAGS]; -+ capo_port_range_t *port_ranges[CAPO_RULE_MAX_FLAGS]; -+ u32 *ipport_ipsets[CAPO_RULE_MAX_FLAGS]; -+} capo_rule_t; -+ -+extern capo_rule_t *capo_rules; -+ -+int capo_rule_delete (u32 id); -+int capo_rule_update (u32 *id, capo_rule_action_t action, -+ ip_address_family_t af, capo_rule_filter_t *filters, -+ capo_rule_entry_t *entries); -+u8 *format_capo_rule (u8 *s, va_list *args); -+capo_rule_t *capo_rule_get_if_exists (u32 index); -+ -+#endif -+ -+/* -+ * fd.io coding-style-patch-verification: ON -+ * -+ * Local Variables: -+ * eval: (c-set-style "gnu") -+ * End: -+ */ -diff --git a/src/plugins/capo/capo_test.c b/src/plugins/capo/capo_test.c -new file mode 100644 -index 000000000..8bfa4ae29 ---- /dev/null -+++ b/src/plugins/capo/capo_test.c -@@ -0,0 +1,490 @@ -+/* -+ * Copyright (c) 2015 Cisco and/or its affiliates. -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at: -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+ * See the License for the specific language governing permissions and -+ * limitations under the License. -+ */ -+/* -+ *------------------------------------------------------------------ -+ * acl_test.c - test harness plugin -+ *------------------------------------------------------------------ -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#define __plugin_msg_base capo_test_main.msg_id_base -+#include -+ -+uword unformat_sw_if_index (unformat_input_t *input, va_list *args); -+ -+/* Declare message IDs */ -+#include -+#include -+#define vl_endianfun /* define message structures */ -+#include -+#undef vl_endianfun -+ -+typedef struct -+{ -+ /* API message ID base */ -+ u16 msg_id_base; -+ vat_main_t *vat_main; -+} capo_test_main_t; -+ -+capo_test_main_t capo_test_main; -+ -+/* NAME: capo_get_version_reply */ -+static void -+vl_api_capo_get_version_reply_t_handler (vl_api_capo_get_version_reply_t *mp) -+{ -+ vat_main_t *vam = capo_test_main.vat_main; -+ clib_warning ("Calico Policy plugin version: %d.%d", ntohl (mp->major), -+ ntohl (mp->minor)); -+ vam->result_ready = 1; -+} -+ -+/* NAME: capo_control_ping_reply */ -+static void -+vl_api_capo_control_ping_reply_t_handler (vl_api_capo_control_ping_reply_t *mp) -+{ -+ vat_main_t *vam = capo_test_main.vat_main; -+ i32 retval = ntohl (mp->retval); -+ if (vam->async_mode) -+ { -+ vam->async_errors += (retval < 0); -+ } -+ else -+ { -+ vam->retval = retval; -+ vam->result_ready = 1; -+ } -+} -+ -+/* NAME: ipset_create_reply */ -+static void -+vl_api_capo_ipset_create_reply_t_handler (vl_api_capo_ipset_create_reply_t *mp) -+{ -+ vat_main_t *vam = capo_test_main.vat_main; -+ clib_warning ("Got ipset_create_reply..."); -+ vam->result_ready = 1; -+} -+ -+/* NAME: rule_create_reply */ -+static void -+vl_api_capo_rule_create_reply_t_handler (vl_api_capo_rule_create_reply_t *mp) -+{ -+ vat_main_t *vam = capo_test_main.vat_main; -+ clib_warning ("Got rule_create_reply..."); -+ vam->result_ready = 1; -+} -+ -+/* NAME: policy_create_reply */ -+static void -+vl_api_capo_policy_create_reply_t_handler ( -+ vl_api_capo_policy_create_reply_t *mp) -+{ -+ vat_main_t *vam = capo_test_main.vat_main; -+ clib_warning ("Got policy_create_reply..."); -+ vam->result_ready = 1; -+} -+ -+/* NAME: capo_get_version */ -+ -+static int -+api_capo_get_version (vat_main_t *vam) -+{ -+ capo_test_main_t *cptm = &capo_test_main; -+ unformat_input_t *i = vam->input; -+ vl_api_capo_get_version_t *mp; -+ u32 msg_size = sizeof (*mp); -+ int ret; -+ -+ vam->result_ready = 0; -+ mp = vl_msg_api_alloc_as_if_client (msg_size); -+ memset (mp, 0, msg_size); -+ mp->_vl_msg_id = ntohs (VL_API_CAPO_GET_VERSION + cptm->msg_id_base); -+ mp->client_index = vam->my_client_index; -+ -+ /* FIXME: do something here */ -+ -+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) -+ { -+ } -+ -+ /* send it... */ -+ S (mp); -+ -+ /* Wait for a reply... */ -+ W (ret); -+ return ret; -+} -+ -+/* NAME: capo_control_ping */ -+ -+static int -+api_capo_control_ping (vat_main_t *vam) -+{ -+ capo_test_main_t *cptm = &capo_test_main; -+ unformat_input_t *i = vam->input; -+ vl_api_capo_control_ping_t *mp; -+ u32 msg_size = sizeof (*mp); -+ int ret; -+ -+ vam->result_ready = 0; -+ mp = vl_msg_api_alloc_as_if_client (msg_size); -+ memset (mp, 0, msg_size); -+ mp->_vl_msg_id = ntohs (VL_API_CAPO_CONTROL_PING + cptm->msg_id_base); -+ mp->client_index = vam->my_client_index; -+ -+ /* FIXME: do something here */ -+ -+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) -+ { -+ } -+ -+ /* send it... */ -+ S (mp); -+ -+ /* Wait for a reply... */ -+ W (ret); -+ return ret; -+} -+ -+/* NAME: ipset_create */ -+ -+static int -+api_capo_ipset_create (vat_main_t *vam) -+{ -+ capo_test_main_t *cptm = &capo_test_main; -+ unformat_input_t *i = vam->input; -+ vl_api_capo_ipset_create_t *mp; -+ u32 msg_size = sizeof (*mp); -+ int ret; -+ -+ vam->result_ready = 0; -+ mp = vl_msg_api_alloc_as_if_client (msg_size); -+ memset (mp, 0, msg_size); -+ mp->_vl_msg_id = ntohs (VL_API_CAPO_IPSET_CREATE + cptm->msg_id_base); -+ mp->client_index = vam->my_client_index; -+ -+ /* FIXME: do something here */ -+ -+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) -+ { -+ } -+ -+ /* send it... */ -+ S (mp); -+ -+ /* Wait for a reply... */ -+ W (ret); -+ return ret; -+} -+ -+/* NAME: ipset_add_del_members */ -+ -+static int -+api_capo_ipset_add_del_members (vat_main_t *vam) -+{ -+ capo_test_main_t *cptm = &capo_test_main; -+ unformat_input_t *i = vam->input; -+ vl_api_capo_ipset_add_del_members_t *mp; -+ u32 msg_size = sizeof (*mp); -+ int ret; -+ -+ vam->result_ready = 0; -+ mp = vl_msg_api_alloc_as_if_client (msg_size); -+ memset (mp, 0, msg_size); -+ mp->_vl_msg_id = -+ ntohs (VL_API_CAPO_IPSET_ADD_DEL_MEMBERS + cptm->msg_id_base); -+ mp->client_index = vam->my_client_index; -+ -+ /* FIXME: do something here */ -+ -+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) -+ { -+ } -+ -+ /* send it... */ -+ S (mp); -+ -+ /* Wait for a reply... */ -+ W (ret); -+ return ret; -+} -+ -+/* NAME: ipset_delete */ -+ -+static int -+api_capo_ipset_delete (vat_main_t *vam) -+{ -+ capo_test_main_t *cptm = &capo_test_main; -+ unformat_input_t *i = vam->input; -+ vl_api_capo_ipset_delete_t *mp; -+ u32 msg_size = sizeof (*mp); -+ int ret; -+ -+ vam->result_ready = 0; -+ mp = vl_msg_api_alloc_as_if_client (msg_size); -+ memset (mp, 0, msg_size); -+ mp->_vl_msg_id = ntohs (VL_API_CAPO_IPSET_DELETE + cptm->msg_id_base); -+ mp->client_index = vam->my_client_index; -+ -+ /* FIXME: do something here */ -+ -+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) -+ { -+ } -+ -+ /* send it... */ -+ S (mp); -+ -+ /* Wait for a reply... */ -+ W (ret); -+ return ret; -+} -+ -+/* NAME: rule_create */ -+ -+static int -+api_capo_rule_create (vat_main_t *vam) -+{ -+ capo_test_main_t *cptm = &capo_test_main; -+ unformat_input_t *i = vam->input; -+ vl_api_capo_rule_create_t *mp; -+ u32 msg_size = sizeof (*mp); -+ int ret; -+ -+ vam->result_ready = 0; -+ mp = vl_msg_api_alloc_as_if_client (msg_size); -+ memset (mp, 0, msg_size); -+ mp->_vl_msg_id = ntohs (VL_API_CAPO_RULE_CREATE + cptm->msg_id_base); -+ mp->client_index = vam->my_client_index; -+ -+ /* FIXME: do something here */ -+ -+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) -+ { -+ } -+ -+ /* send it... */ -+ S (mp); -+ -+ /* Wait for a reply... */ -+ W (ret); -+ return ret; -+} -+ -+/* NAME: rule_update */ -+ -+static int -+api_capo_rule_update (vat_main_t *vam) -+{ -+ capo_test_main_t *cptm = &capo_test_main; -+ unformat_input_t *i = vam->input; -+ vl_api_capo_rule_update_t *mp; -+ u32 msg_size = sizeof (*mp); -+ int ret; -+ -+ vam->result_ready = 0; -+ mp = vl_msg_api_alloc_as_if_client (msg_size); -+ memset (mp, 0, msg_size); -+ mp->_vl_msg_id = ntohs (VL_API_CAPO_RULE_UPDATE + cptm->msg_id_base); -+ mp->client_index = vam->my_client_index; -+ -+ /* FIXME: do something here */ -+ -+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) -+ { -+ } -+ -+ /* send it... */ -+ S (mp); -+ -+ /* Wait for a reply... */ -+ W (ret); -+ return ret; -+} -+ -+/* NAME: rule_delete */ -+ -+static int -+api_capo_rule_delete (vat_main_t *vam) -+{ -+ capo_test_main_t *cptm = &capo_test_main; -+ unformat_input_t *i = vam->input; -+ vl_api_capo_rule_delete_t *mp; -+ u32 msg_size = sizeof (*mp); -+ int ret; -+ -+ vam->result_ready = 0; -+ mp = vl_msg_api_alloc_as_if_client (msg_size); -+ memset (mp, 0, msg_size); -+ mp->_vl_msg_id = ntohs (VL_API_CAPO_RULE_DELETE + cptm->msg_id_base); -+ mp->client_index = vam->my_client_index; -+ -+ /* FIXME: do something here */ -+ -+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) -+ { -+ } -+ -+ /* send it... */ -+ S (mp); -+ -+ /* Wait for a reply... */ -+ W (ret); -+ return ret; -+} -+ -+/* NAME: policy_create */ -+ -+static int -+api_capo_policy_create (vat_main_t *vam) -+{ -+ capo_test_main_t *cptm = &capo_test_main; -+ unformat_input_t *i = vam->input; -+ vl_api_capo_policy_create_t *mp; -+ u32 msg_size = sizeof (*mp); -+ int ret; -+ -+ vam->result_ready = 0; -+ mp = vl_msg_api_alloc_as_if_client (msg_size); -+ memset (mp, 0, msg_size); -+ mp->_vl_msg_id = ntohs (VL_API_CAPO_POLICY_CREATE + cptm->msg_id_base); -+ mp->client_index = vam->my_client_index; -+ -+ /* FIXME: do something here */ -+ -+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) -+ { -+ } -+ -+ /* send it... */ -+ S (mp); -+ -+ /* Wait for a reply... */ -+ W (ret); -+ return ret; -+} -+ -+/* NAME: policy_update */ -+ -+static int -+api_capo_policy_update (vat_main_t *vam) -+{ -+ capo_test_main_t *cptm = &capo_test_main; -+ unformat_input_t *i = vam->input; -+ vl_api_capo_policy_update_t *mp; -+ u32 msg_size = sizeof (*mp); -+ int ret; -+ -+ vam->result_ready = 0; -+ mp = vl_msg_api_alloc_as_if_client (msg_size); -+ memset (mp, 0, msg_size); -+ mp->_vl_msg_id = ntohs (VL_API_CAPO_POLICY_UPDATE + cptm->msg_id_base); -+ mp->client_index = vam->my_client_index; -+ -+ /* FIXME: do something here */ -+ -+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) -+ { -+ } -+ -+ /* send it... */ -+ S (mp); -+ -+ /* Wait for a reply... */ -+ W (ret); -+ return ret; -+} -+ -+/* NAME: policy_delete */ -+ -+static int -+api_capo_policy_delete (vat_main_t *vam) -+{ -+ capo_test_main_t *cptm = &capo_test_main; -+ unformat_input_t *i = vam->input; -+ vl_api_capo_policy_delete_t *mp; -+ u32 msg_size = sizeof (*mp); -+ int ret; -+ -+ vam->result_ready = 0; -+ mp = vl_msg_api_alloc_as_if_client (msg_size); -+ memset (mp, 0, msg_size); -+ mp->_vl_msg_id = ntohs (VL_API_CAPO_POLICY_DELETE + cptm->msg_id_base); -+ mp->client_index = vam->my_client_index; -+ -+ /* FIXME: do something here */ -+ -+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) -+ { -+ } -+ -+ /* send it... */ -+ S (mp); -+ -+ /* Wait for a reply... */ -+ W (ret); -+ return ret; -+} -+ -+/* NAME: configure_policies */ -+ -+static int -+api_capo_configure_policies (vat_main_t *vam) -+{ -+ capo_test_main_t *cptm = &capo_test_main; -+ unformat_input_t *i = vam->input; -+ vl_api_capo_configure_policies_t *mp; -+ u32 msg_size = sizeof (*mp); -+ int ret; -+ -+ vam->result_ready = 0; -+ mp = vl_msg_api_alloc_as_if_client (msg_size); -+ memset (mp, 0, msg_size); -+ mp->_vl_msg_id = ntohs (VL_API_CAPO_CONFIGURE_POLICIES + cptm->msg_id_base); -+ mp->client_index = vam->my_client_index; -+ -+ /* FIXME: do something here */ -+ -+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) -+ { -+ } -+ -+ /* send it... */ -+ S (mp); -+ -+ /* Wait for a reply... */ -+ W (ret); -+ return ret; -+} -+ -+#define VL_API_LOCAL_SETUP_MESSAGE_ID_TABLE local_setup_message_id_table -+static void -+local_setup_message_id_table (vat_main_t *vam) -+{ -+ // hash_set_mem (vam->function_by_name, "acl_add_replace_from_file", -+ // api_capo_acl_add_replace_from_file); hash_set_mem (vam->help_by_name, -+ // "acl_add_replace_from_file", "filename [permit] -+ // [append-default-permit]"); -+} -+ -+#include -diff --git a/src/plugins/capo/test/test_capo.py b/src/plugins/capo/test/test_capo.py -new file mode 100644 -index 000000000..401a7abd5 ---- /dev/null -+++ b/src/plugins/capo/test/test_capo.py -@@ -0,0 +1,807 @@ -+#!/usr/bin/env python3 -+ -+import random -+import unittest -+from ipaddress import (IPv4Address, IPv4Network, IPv6Address, IPv6Network, -+ ip_address, ip_network) -+from itertools import product -+ -+from framework import VppTestCase, VppTestRunner -+from scapy.layers.inet import (ICMP, IP, TCP, UDP, ICMPerror, IPerror, -+ TCPerror, UDPerror) -+from scapy.layers.inet6 import (ICMPv6DestUnreach, ICMPv6EchoReply, -+ ICMPv6EchoRequest, IPerror6, IPv6) -+from scapy.layers.l2 import Ether -+from scapy.packet import Raw -+from vpp_ip import INVALID_INDEX, DpoProto -+from vpp_object import VppObject -+from vpp_papi import VppEnum -+ -+icmp4_type = 8 # echo request -+icmp4_code = 3 -+icmp6_type = 128 # echo request -+icmp6_code = 3 -+tcp_protocol = 6 -+icmp_protocol = 1 -+icmp6_protocol = 58 -+udp_protocol = 17 -+src_l4 = 1234 -+dst_l4 = 4321 -+ -+ -+def random_payload(): -+ return Raw(load=bytearray(random.getrandbits(8) for _ in range(20))) -+ -+ -+class VppCapoPolicyItem(): -+ def __init__(self, is_inbound, rule_id): -+ self._is_inbound = is_inbound -+ self._rule_id = rule_id -+ -+ def encode(self): -+ return {'rule_id': self._rule_id, 'is_inbound': self._is_inbound} -+ -+ -+class VppCapoPolicy(VppObject): -+ def __init__(self, test, rules): -+ self._test = test -+ self._rules = rules -+ self.encoded_rules = [] -+ self.init_rules() -+ -+ def init_rules(self): -+ self.encoded_rules = [] -+ for rule in self._rules: -+ self.encoded_rules.append(rule.encode()) -+ -+ def add_vpp_config(self): -+ r = self._test.vapi.capo_policy_create( -+ len(self.encoded_rules), -+ self.encoded_rules) -+ self._test.assertEqual(0, r.retval) -+ self._test.registry.register(self, self._test.logger) -+ self._test.logger.info("capo_policy_create retval=" + str(r.retval)) -+ self._policy_id = r.policy_id -+ self._test.logger.info(self._test.vapi.cli("show capo policies verbose")) -+ -+ def capo_policy_update(self, rules): -+ self._rules = rules -+ self.init_rules() -+ r = self._test.vapi.capo_policy_update( -+ self._policy_id, -+ len(self.encoded_rules), -+ self.encoded_rules) -+ self._test.assertEqual(0, r.retval) -+ -+ def capo_policy_delete(self): -+ r = self._test.vapi.capo_policy_delete(self._policy_id) -+ self._test.assertEqual(0, r.retval) -+ self._test.logger.info(self._test.vapi.cli("show capo policies")) -+ -+ def remove_vpp_config(self): -+ self.capo_policy_delete() -+ -+ def query_vpp_config(self): -+ self._test.logger.info("query vpp config") -+ self._test.logger.info(self._test.vapi.cli("show capo policies verbose")) -+ -+ -+class VppCapoFilter: -+ def __init__(self, type=None, value=0, should_match=0): -+ self._filter_type = type if type != None else FILTER_TYPE_NONE -+ self._filter_value = value -+ self._should_match = should_match -+ -+ def encode(self): -+ return {'type': self._filter_type, -+ 'value': self._filter_value, -+ 'should_match': self._should_match} -+ -+ -+class VppCapoRule(VppObject): -+ def __init__(self, test, is_v6, action, filters=[], matches=[]): -+ self._test = test -+ # This is actually unused -+ self._af = 255 -+ self.init_rule(action, filters, matches) -+ -+ def vpp_id(self): -+ return self._rule_id -+ -+ def init_rule(self, action, filters=[], matches=[]): -+ self._action = action -+ self._filters = filters -+ self._matches = matches -+ self.encoded_filters = [] -+ for filter in self._filters: -+ self.encoded_filters.append(filter.encode()) -+ while len(self.encoded_filters) < 3: -+ self.encoded_filters.append(VppCapoFilter().encode()) -+ self._test.assertEqual(len(self.encoded_filters), 3) -+ -+ def add_vpp_config(self): -+ r = self._test.vapi.capo_rule_create( -+ {'af': self._af, -+ 'action': self._action, -+ 'filters': self.encoded_filters, -+ 'num_entries': len(self._matches), -+ 'matches': self._matches -+ }) -+ self._test.assertEqual(0, r.retval) -+ self._test.registry.register(self, self._test.logger) -+ self._test.logger.info("capo_rule_create retval=" + str(r.retval)) -+ self._rule_id = r.rule_id -+ self._test.logger.info("rules id : " + str(self._rule_id)) -+ self._test.logger.info(self._test.vapi.cli("show capo rules")) -+ -+ def capo_rule_update(self, filters, matches): -+ self.init_rule(self._action, filters, matches) -+ r = self._test.vapi.capo_rule_update( -+ self._rule_id, -+ {'af': self._af, -+ 'action': self._action, -+ 'filters': self.encoded_filters, -+ 'num_entries': len(self._matches), -+ 'matches': self._matches -+ }) -+ self._test.assertEqual(0, r.retval) -+ self._test.registry.register(self, self._test.logger) -+ self._test.logger.info("capo rule update") -+ self._test.logger.info(self._test.vapi.cli("show capo rules")) -+ -+ def capo_rule_delete(self): -+ r = self._test.vapi.capo_rule_delete(self._rule_id) -+ self._test.assertEqual(0, r.retval) -+ self._test.logger.info(self._test.vapi.cli("show capo rules")) -+ -+ def remove_vpp_config(self): -+ self.capo_rule_delete() -+ -+ def query_vpp_config(self): -+ self._test.logger.info("query vpp config") -+ self._test.logger.info(self._test.vapi.cli("show capo rules")) -+ -+ -+class VppCapoIpset(VppObject): -+ def __init__(self, test, type, members): -+ self.test = test -+ self.type = type -+ self.members = members -+ -+ def add_vpp_config(self): -+ r = self.test.vapi.capo_ipset_create(self.type) -+ self.test.assertEqual(0, r.retval) -+ self.vpp_id = r.set_id -+ encoded_members = [] -+ for m in self.members: -+ if self.type == IPSET_TYPE_IP: -+ encoded_members.append({"val":{"address": m}}) -+ elif self.type == IPSET_TYPE_IP_PORT: -+ encoded_members.append({"val":{"tuple": m}}) -+ elif self.type == IPSET_TYPE_NET: -+ encoded_members.append({"val":{"prefix": m}}) -+ r = self.test.vapi.capo_ipset_add_del_members( -+ set_id=self.vpp_id, -+ is_add=True, -+ len=len(encoded_members), -+ members=encoded_members, -+ ) -+ self.test.assertEqual(0, r.retval) -+ -+ def query_vpp_config(self): -+ pass -+ -+ def remove_vpp_config(self): -+ r = self.test.vapi.capo_ipset_delete(set_id=self.vpp_id) -+ self.test.assertEqual(0, r.retval) -+ -+ -+ -+class BaseCapoTest(VppTestCase): -+ @classmethod -+ def setUpClass(self): -+ super(BaseCapoTest, self).setUpClass() -+ # We can't define these before the API is loaded, so here they are... -+ global ACTION_ALLOW, ACTION_DENY, ACTION_PASS, ACTION_LOG -+ ACTION_ALLOW = VppEnum.vl_api_capo_rule_action_t.CAPO_ALLOW -+ ACTION_DENY = VppEnum.vl_api_capo_rule_action_t.CAPO_DENY -+ ACTION_PASS = VppEnum.vl_api_capo_rule_action_t.CAPO_PASS -+ ACTION_LOG = VppEnum.vl_api_capo_rule_action_t.CAPO_LOG -+ global FILTER_TYPE_NONE, FILTER_TYPE_L4_PROTO, FILTER_TYPE_ICMP_CODE, FILTER_TYPE_ICMP_TYPE -+ FILTER_TYPE_NONE = VppEnum.vl_api_capo_rule_filter_type_t.CAPO_RULE_FILTER_NONE_TYPE -+ FILTER_TYPE_L4_PROTO = VppEnum.vl_api_capo_rule_filter_type_t.CAPO_RULE_FILTER_L4_PROTO -+ FILTER_TYPE_ICMP_CODE = VppEnum.vl_api_capo_rule_filter_type_t.CAPO_RULE_FILTER_ICMP_CODE -+ FILTER_TYPE_ICMP_TYPE = VppEnum.vl_api_capo_rule_filter_type_t.CAPO_RULE_FILTER_ICMP_TYPE -+ global ENTRY_CIDR, ENTRY_PORT_RANGE, ENTRY_PORT_IP_SET, ENTRY_IP_SET -+ ENTRY_CIDR = VppEnum.vl_api_capo_entry_type_t.CAPO_CIDR -+ ENTRY_PORT_RANGE = VppEnum.vl_api_capo_entry_type_t.CAPO_PORT_RANGE -+ ENTRY_PORT_IP_SET = VppEnum.vl_api_capo_entry_type_t.CAPO_PORT_IP_SET -+ ENTRY_IP_SET = VppEnum.vl_api_capo_entry_type_t.CAPO_IP_SET -+ global IPSET_TYPE_IP, IPSET_TYPE_IP_PORT, IPSET_TYPE_NET -+ IPSET_TYPE_IP = VppEnum.vl_api_capo_ipset_type_t.CAPO_IP -+ IPSET_TYPE_IP_PORT = VppEnum.vl_api_capo_ipset_type_t.CAPO_IP_AND_PORT -+ IPSET_TYPE_NET = VppEnum.vl_api_capo_ipset_type_t.CAPO_NET -+ -+ self.create_pg_interfaces(range(2)) -+ for i in self.pg_interfaces: -+ i.admin_up() -+ # Add one additional neighbor on each side for tests with different addresses -+ i.generate_remote_hosts(2) -+ i.config_ip4() -+ i.configure_ipv4_neighbors() -+ i.config_ip6() -+ i.configure_ipv6_neighbors() -+ -+ @classmethod -+ def tearDownClass(self): -+ for i in self.pg_interfaces: -+ i.unconfig_ip4() -+ i.unconfig_ip6() -+ i.admin_down() -+ super(BaseCapoTest, self).tearDownClass() -+ -+ -+ def setUp(self): -+ super(BaseCapoTest, self).setUp() -+ -+ def tearDown(self): -+ super(BaseCapoTest, self).tearDown() -+ -+ def configure_policies(self, interface, ingress, egress, profiles, invert_tx_rx): -+ id_list = [] -+ for policy in ingress + egress + profiles: -+ id_list.append(policy._policy_id) -+ -+ r = self.vapi.capo_configure_policies( -+ interface.sw_if_index, -+ len(ingress), -+ len(egress), -+ len(ingress) + len(egress) + len(profiles), -+ id_list, -+ invert_tx_rx) -+ self.assertEqual(0, r.retval) -+ -+ def base_ip_packet(self, is_v6=False, second_src_ip=False, second_dst_ip=False): -+ IP46 = IPv6 if is_v6 else IP -+ src_host = self.pg0.remote_hosts[1 if second_src_ip else 0] -+ dst_host = self.pg1.remote_hosts[1 if second_dst_ip else 0] -+ src_addr = src_host.ip6 if is_v6 else src_host.ip4 -+ dst_addr = dst_host.ip6 if is_v6 else dst_host.ip4 -+ return Ether(src=src_host.mac, dst=self.pg0.local_mac) / IP46(src=src_addr, -+ dst=dst_addr) -+ -+ def do_test_one_rule(self, filters, matches, matching_packets, not_matching_packets): -+ # Caution: because of how vpp works, packets may be reordered (v4 first, v6 next) -+ # which may break the check on received packets -+ # Therefore, in matching packets, all v4 packets must be before all v6 packets -+ self.rule.capo_rule_update(filters, matches) -+ self.send_test_packets(self.pg0, self.pg1, matching_packets, not_matching_packets) -+ -+ def send_test_packets(self, from_if, to_if, passing_packets, dropped_packets): -+ if len(passing_packets) > 0: -+ rxl = self.send_and_expect(from_if, passing_packets, to_if) -+ self.assertEqual(len(rxl), len(passing_packets)) -+ for i in range(len(passing_packets)): -+ rx = rxl[i].payload -+ tx = passing_packets[i].payload -+ tx = tx.__class__(bytes(tx)) # Compute all fields -+ # Remove IP[v6] TTL / checksum that are changed on forwarding -+ if IP in tx: -+ del tx.chksum, tx.ttl, rx.chksum, rx.ttl -+ elif IPv6 in tx: -+ del tx.hlim, rx.hlim -+ self.assertEqual(rx, tx) -+ if len(dropped_packets) > 0: -+ self.send_and_assert_no_replies(from_if, dropped_packets, to_if, timeout=0.1) -+ self.vapi.cli("clear acl-plugin sessions") -+ -+ -+class TestCapoMatches(BaseCapoTest): -+ """ Calico Policies rule matching tests """ -+ @classmethod -+ def setUpClass(self): -+ super(TestCapoMatches, self).setUpClass() -+ -+ @classmethod -+ def tearDownClass(self): -+ super(TestCapoMatches, self).tearDownClass() -+ -+ def setUp(self): -+ super(TestCapoMatches, self).setUp() -+ self.rule = VppCapoRule(self, is_v6=False, action=ACTION_ALLOW) -+ self.rule.add_vpp_config() -+ self.policy = VppCapoPolicy(self, [VppCapoPolicyItem(is_inbound=1, rule_id=self.rule.vpp_id())]) -+ self.policy.add_vpp_config() -+ self.configure_policies(self.pg1, [self.policy], [], []) -+ self.src_ip_ipset = VppCapoIpset(self, IPSET_TYPE_IP, [self.pg0.remote_ip4, self.pg0.remote_ip6]) -+ self.src_ip_ipset.add_vpp_config() -+ self.dst_ip_ipset = VppCapoIpset(self, IPSET_TYPE_IP, [self.pg1.remote_ip4, self.pg1.remote_ip6]) -+ self.dst_ip_ipset.add_vpp_config() -+ self.src_net_ipset = VppCapoIpset(self, IPSET_TYPE_NET, [self.pg0.remote_ip4+"/32", self.pg0.remote_ip6+"/128"]) -+ self.src_net_ipset.add_vpp_config() -+ self.dst_net_ipset = VppCapoIpset(self, IPSET_TYPE_NET, [self.pg1.remote_ip4+"/32", self.pg1.remote_ip6+"/128"]) -+ self.dst_net_ipset.add_vpp_config() -+ self.src_ipport_ipset = VppCapoIpset(self, IPSET_TYPE_IP_PORT, [ -+ {"address":self.pg0.remote_ip4, "l4_proto": tcp_protocol, "port": src_l4}, -+ {"address":self.pg0.remote_ip6, "l4_proto": tcp_protocol, "port": src_l4} -+ ]) -+ self.src_ipport_ipset.add_vpp_config() -+ self.dst_ipport_ipset = VppCapoIpset(self, IPSET_TYPE_IP_PORT, [ -+ {"address":self.pg1.remote_ip4, "l4_proto": tcp_protocol, "port": dst_l4}, -+ {"address":self.pg1.remote_ip6, "l4_proto": tcp_protocol, "port": dst_l4} -+ ]) -+ self.dst_ipport_ipset.add_vpp_config() -+ -+ def tearDown(self): -+ self.vapi.cli("clear acl-plugin sessions") -+ self.configure_policies(self.pg1, [], [], []) -+ self.policy.capo_policy_delete() -+ self.rule.capo_rule_delete() -+ super(TestCapoMatches, self).tearDown() -+ -+ def test_empty_rule(self): -+ # Empty rule matches everything -+ valid = [ -+ self.base_ip_packet(False) / TCP(sport=src_l4, dport=dst_l4) / random_payload(), -+ self.base_ip_packet(False) / UDP(sport=src_l4, dport=dst_l4) / random_payload(), -+ self.base_ip_packet(False) / ICMP(type=icmp4_type, code=icmp4_code) / random_payload(), -+ self.base_ip_packet(True) / TCP(sport=src_l4, dport=dst_l4) / random_payload(), -+ self.base_ip_packet(True) / UDP(sport=src_l4, dport=dst_l4) / random_payload(), -+ self.base_ip_packet(True) / ICMPv6EchoRequest(type=icmp6_type, code=icmp6_code) / random_payload(), -+ ] -+ self.do_test_one_rule([], [], valid, []) -+ -+ def capo_test_icmp(self, is_v6): -+ ICMP46 = ICMPv6EchoRequest if is_v6 else ICMP -+ icmp_type = icmp6_type if is_v6 else icmp4_type -+ icmp_code = icmp6_code if is_v6 else icmp4_code -+ -+ # Define filter on ICMP type -+ filters = [VppCapoFilter(FILTER_TYPE_ICMP_TYPE, value=icmp_type, should_match=1)] -+ valid = self.base_ip_packet(is_v6) / ICMP46(type=icmp_type, code=icmp_code) / random_payload() -+ invalid = self.base_ip_packet(is_v6) / ICMP46(type=11, code=22) / random_payload() -+ self.do_test_one_rule(filters, [], [valid], [invalid]) -+ -+ # Define filter on ICMP type / should match = 0 -+ filters = [VppCapoFilter(FILTER_TYPE_ICMP_TYPE, value=11, should_match=0)] -+ invalid = self.base_ip_packet(is_v6) / ICMP46(type=11, code=icmp_code) / random_payload() -+ valid = self.base_ip_packet(is_v6) / ICMP46(type=icmp_type, code=icmp_code) / random_payload() -+ self.do_test_one_rule(filters, [], [valid], [invalid]) -+ -+ def test_icmp4_type(self): -+ self.capo_test_icmp(is_v6=False) -+ -+ def test_icmp6_type(self): -+ self.capo_test_icmp(is_v6=True) -+ -+ def capo_test_icmp_code(self, is_v6): -+ ICMP46 = ICMPv6EchoRequest if is_v6 else ICMP -+ icmp_type = 1 if is_v6 else 3 # Destination unreachable -+ icmp_code = 9 # admin prohibited -+ -+ # Define filter on ICMP type -+ filters = [VppCapoFilter(FILTER_TYPE_ICMP_CODE, value=icmp_code, should_match=1)] -+ valid = self.base_ip_packet(is_v6) / ICMP46(type=icmp_type, code=icmp_code) / random_payload() -+ invalid = self.base_ip_packet(is_v6) / ICMP46(type=icmp_type, code=icmp_code-1) / random_payload() -+ self.do_test_one_rule(filters, [], [valid], [invalid]) -+ -+ # Define filter on ICMP type / should match = 0 -+ filters = [VppCapoFilter(FILTER_TYPE_ICMP_CODE, value=icmp_code, should_match=0)] -+ valid = self.base_ip_packet(is_v6) / ICMP46(type=icmp_type, code=icmp_code+1) / random_payload() -+ invalid = self.base_ip_packet(is_v6) / ICMP46(type=icmp_type, code=icmp_code) / random_payload() -+ self.do_test_one_rule(filters, [], [valid], [invalid]) -+ -+ def test_icmp4_code(self): -+ self.capo_test_icmp(is_v6=False) -+ -+ def test_icmp6_code(self): -+ self.capo_test_icmp(is_v6=True) -+ -+ def capo_test_l4proto(self, is_v6, l4proto): -+ filter_value = 0 -+ if l4proto == TCP: -+ filter_value = tcp_protocol -+ elif l4proto == UDP: -+ filter_value = udp_protocol -+ -+ # Define filter on l4proto type -+ filters = [VppCapoFilter(FILTER_TYPE_L4_PROTO, value=filter_value, should_match=1)] -+ -+ # Send tcp pg0 -> pg1 -+ valid = self.base_ip_packet(is_v6) / l4proto(sport=src_l4, dport=dst_l4) / random_payload() -+ # send icmp packet (different l4proto) and expect packet is filtered -+ invalid = self.base_ip_packet(is_v6) / ICMP(type=8, code=3) / random_payload() -+ self.do_test_one_rule(filters, [], [valid], [invalid]) -+ -+ # Define filter on l4proto / should match = 0 -+ filters = [VppCapoFilter(FILTER_TYPE_L4_PROTO, value=filter_value, should_match=0)] -+ # send l4proto packet and expect it is filtered -+ invalid = self.base_ip_packet(is_v6) / l4proto(sport=src_l4, dport=dst_l4) / random_payload() -+ # send icmp packet (different l4proto) and expect it is not filtered -+ valid = self.base_ip_packet(is_v6) / ICMP(type=8, code=3) / random_payload() -+ self.do_test_one_rule(filters, [], [valid], [invalid]) -+ -+ def test_l4proto_tcp4(self): -+ self.capo_test_l4proto(False, TCP) -+ -+ def test_l4proto_tcp6(self): -+ self.capo_test_l4proto(True, TCP) -+ -+ def test_l4proto_udp4(self): -+ self.capo_test_l4proto(False, UDP) -+ -+ def test_l4proto_udp6(self): -+ self.capo_test_l4proto(True, UDP) -+ -+ def test_prefixes_ip6(self): -+ self.test_prefixes(True) -+ -+ def test_prefixes(self, is_ip6=False): -+ pload = lambda : TCP(sport=src_l4, dport=dst_l4) / random_payload() -+ dst_ip_match = self.pg1.remote_ip6 + "/128" if is_ip6 else self.pg1.remote_ip4 + "/32" -+ match = {"is_src": False, "is_not": False, "type": ENTRY_CIDR, "data": {"cidr": dst_ip_match}} -+ valid = self.base_ip_packet(is_ip6) / pload() -+ invalid = self.base_ip_packet(is_ip6, second_dst_ip=True) / pload() -+ self.do_test_one_rule([], [match], [valid], [invalid]) -+ -+ match['is_not'] = True -+ self.do_test_one_rule([], [match], [invalid], [valid]) -+ -+ src_ip_match = self.pg0.remote_ip6 + "/128" if is_ip6 else self.pg0.remote_ip4 + "/32" -+ match = {"is_src": True, "is_not": False, "type": ENTRY_CIDR, "data": {"cidr": src_ip_match}} -+ valid = self.base_ip_packet(is_ip6) / pload() -+ invalid = self.base_ip_packet(is_ip6, second_src_ip=True) / pload() -+ self.do_test_one_rule([], [match], [valid], [invalid]) -+ -+ match['is_not'] = True -+ self.do_test_one_rule([], [match], [invalid], [valid]) -+ -+ def test_port_ranges_ip6(self): -+ self.test_prefixes(True) -+ -+ def test_port_ranges(self, is_ip6=False): -+ base = self.base_ip_packet(is_ip6) -+ test_port = 5123 -+ # Test all match kinds -+ match = {"is_src": False, "is_not": False, "type": ENTRY_PORT_RANGE, -+ "data": {"port_range": {"start": test_port, "end": test_port}}} -+ valid = base / TCP(sport=test_port, dport=test_port) / random_payload() -+ invalid = [ -+ base / TCP(sport=test_port, dport=test_port+1) / random_payload(), -+ base / TCP(sport=test_port, dport=test_port-1) / random_payload(), -+ ] -+ self.do_test_one_rule([], [match], [valid], invalid) -+ -+ match['is_not'] = True -+ self.do_test_one_rule([], [match], invalid, [valid]) -+ -+ match = {"is_src": True, "is_not": False, "type": ENTRY_PORT_RANGE, -+ "data": {"port_range": {"start": test_port, "end": test_port}}} -+ valid = base / TCP(sport=test_port, dport=test_port) / random_payload() -+ invalid = [ -+ base / TCP(sport=test_port+1, dport=test_port) / random_payload(), -+ base / TCP(sport=test_port-1, dport=test_port) / random_payload(), -+ ] -+ self.do_test_one_rule([], [match], [valid], invalid) -+ -+ match['is_not'] = True -+ self.do_test_one_rule([], [match], invalid, [valid]) -+ -+ # Test port ranges with several ports & UDP -+ match = {"is_src": False, "is_not": False, "type": ENTRY_PORT_RANGE, -+ "data": {"port_range": {"start": test_port, "end": test_port+10}}} -+ valid = [ -+ base / TCP(sport=test_port, dport=test_port) / random_payload(), -+ base / TCP(sport=test_port, dport=test_port+5) / random_payload(), -+ base / TCP(sport=test_port, dport=test_port+10) / random_payload(), -+ base / UDP(sport=test_port, dport=test_port) / random_payload(), -+ base / UDP(sport=test_port, dport=test_port+5) / random_payload(), -+ base / UDP(sport=test_port, dport=test_port+10) / random_payload(), -+ ] -+ invalid = [ -+ base / TCP(sport=test_port, dport=test_port-1) / random_payload(), -+ base / TCP(sport=test_port, dport=test_port+11) / random_payload(), -+ ] -+ self.do_test_one_rule([], [match], valid, invalid) -+ -+ -+ def test_ip_ipset_ip6(self): -+ self.test_ip_ipset(True) -+ -+ def test_ip_ipset(self, is_ip6=False): -+ pload = lambda : TCP(sport=src_l4, dport=dst_l4) / random_payload() -+ dst_ip_match = self.pg1.remote_ip6 + "/128" if is_ip6 else self.pg1.remote_ip4 + "/32" -+ match = {"is_src": False, "is_not": False, "type": ENTRY_IP_SET, -+ "data": {"set_id": {"set_id": self.dst_ip_ipset.vpp_id}}} -+ valid = self.base_ip_packet(is_ip6) / pload() -+ invalid = self.base_ip_packet(is_ip6, second_dst_ip=True) / pload() -+ self.do_test_one_rule([], [match], [valid], [invalid]) -+ -+ match['is_not'] = True -+ self.do_test_one_rule([], [match], [invalid], [valid]) -+ -+ src_ip_match = self.pg0.remote_ip6 + "/128" if is_ip6 else self.pg0.remote_ip4 + "/32" -+ match = {"is_src": True, "is_not": False, "type": ENTRY_IP_SET, -+ "data": {"set_id": {"set_id": self.src_ip_ipset.vpp_id}}} -+ valid = self.base_ip_packet(is_ip6) / pload() -+ invalid = self.base_ip_packet(is_ip6, second_src_ip=True) / pload() -+ self.do_test_one_rule([], [match], [valid], [invalid]) -+ -+ match['is_not'] = True -+ self.do_test_one_rule([], [match], [invalid], [valid]) -+ -+ def test_net_ipset_ip6(self): -+ self.test_net_ipset(True) -+ -+ def test_net_ipset(self, is_ip6=False): -+ pload = lambda : TCP(sport=src_l4, dport=dst_l4) / random_payload() -+ dst_ip_match = self.pg1.remote_ip6 + "/128" if is_ip6 else self.pg1.remote_ip4 + "/32" -+ match = {"is_src": False, "is_not": False, "type": ENTRY_IP_SET, -+ "data": {"set_id": {"set_id": self.dst_net_ipset.vpp_id}}} -+ valid = self.base_ip_packet(is_ip6) / pload() -+ invalid = self.base_ip_packet(is_ip6, second_dst_ip=True) / pload() -+ self.do_test_one_rule([], [match], [valid], [invalid]) -+ -+ match['is_not'] = True -+ self.do_test_one_rule([], [match], [invalid], [valid]) -+ -+ src_ip_match = self.pg0.remote_ip6 + "/128" if is_ip6 else self.pg0.remote_ip4 + "/32" -+ match = {"is_src": True, "is_not": False, "type": ENTRY_IP_SET, -+ "data": {"set_id": {"set_id": self.src_net_ipset.vpp_id}}} -+ valid = self.base_ip_packet(is_ip6) / pload() -+ invalid = self.base_ip_packet(is_ip6, second_src_ip=True) / pload() -+ self.do_test_one_rule([], [match], [valid], [invalid]) -+ -+ match['is_not'] = True -+ self.do_test_one_rule([], [match], [invalid], [valid]) -+ -+ def test_ipport_ipset_ip6(self): -+ self.test_ipport_ipset(True) -+ -+ def test_ipport_ipset(self, is_ip6=False): -+ match = {"is_src": False, "is_not": False, "type": ENTRY_PORT_IP_SET, -+ "data": {"set_id": {"set_id": self.dst_ipport_ipset.vpp_id}}} -+ valid = self.base_ip_packet(is_ip6) / TCP(sport=src_l4, dport=dst_l4) / random_payload() -+ invalid = [ # Change all criteria: address, proto, port -+ self.base_ip_packet(is_ip6, second_dst_ip=True) / TCP(sport=src_l4, dport=dst_l4) / random_payload(), -+ self.base_ip_packet(is_ip6) / UDP(sport=src_l4, dport=dst_l4) / random_payload(), -+ self.base_ip_packet(is_ip6) / TCP(sport=src_l4, dport=dst_l4+1) / random_payload(), -+ ] -+ self.do_test_one_rule([], [match], [valid], invalid) -+ -+ match['is_not'] = True -+ self.do_test_one_rule([], [match], invalid, [valid]) -+ -+ match = {"is_src": True, "is_not": False, "type": ENTRY_PORT_IP_SET, -+ "data": {"set_id": {"set_id": self.src_ipport_ipset.vpp_id}}} -+ valid = self.base_ip_packet(is_ip6) / TCP(sport=src_l4, dport=dst_l4) / random_payload() -+ invalid = [ # Change all criteria: address, proto, port -+ self.base_ip_packet(is_ip6, second_src_ip=True) / TCP(sport=src_l4, dport=dst_l4) / random_payload(), -+ self.base_ip_packet(is_ip6) / UDP(sport=src_l4, dport=dst_l4) / random_payload(), -+ self.base_ip_packet(is_ip6) / TCP(sport=src_l4+1, dport=dst_l4) / random_payload(), -+ ] -+ self.do_test_one_rule([], [match], [valid], invalid) -+ -+ match['is_not'] = True -+ self.do_test_one_rule([], [match], invalid, [valid]) -+ -+ # Calico specificity: if a rule has port ranges and ipport ipsets, a packet matches -+ # the rule if it matches either category -+ def test_port_range_and_ipport_ipset_ip6(self): -+ self.test_port_range_and_ipport_ipset(True) -+ -+ def test_port_range_and_ipport_ipset(self, is_ip6=False): -+ # Test all match types to exercies all code (but not all combinations) -+ test_port=4569 -+ matches = [ -+ {"is_src": False, "is_not": False, "type": ENTRY_PORT_IP_SET, -+ "data": {"set_id": {"set_id": self.dst_ipport_ipset.vpp_id}}}, -+ {"is_src": False, "is_not": False, "type": ENTRY_PORT_RANGE, -+ "data": {"port_range": {"start": test_port, "end": test_port}}}, -+ ] -+ valid = [ -+ self.base_ip_packet(is_ip6) / TCP(sport=src_l4, dport=dst_l4) / random_payload(), -+ self.base_ip_packet(is_ip6) / TCP(sport=src_l4, dport=test_port) / random_payload(), -+ self.base_ip_packet(is_ip6) / UDP(sport=src_l4, dport=test_port) / random_payload(), -+ self.base_ip_packet(is_ip6, second_src_ip=True) / TCP(sport=src_l4, dport=test_port) / random_payload(), -+ self.base_ip_packet(is_ip6, second_dst_ip=True) / TCP(sport=src_l4, dport=test_port) / random_payload(), -+ ] -+ invalid = [ -+ self.base_ip_packet(is_ip6, second_dst_ip=True) / TCP(sport=src_l4, dport=dst_l4) / random_payload(), -+ self.base_ip_packet(is_ip6) / UDP(sport=src_l4, dport=dst_l4) / random_payload(), -+ self.base_ip_packet(is_ip6) / TCP(sport=src_l4, dport=(dst_l4+test_port)//2) / random_payload(), -+ ] -+ self.do_test_one_rule([], matches, valid, invalid) -+ -+ for match in matches: -+ match['is_not'] = True -+ self.do_test_one_rule([], matches, invalid, valid) -+ -+ matches = [ -+ {"is_src": True, "is_not": False, "type": ENTRY_PORT_IP_SET, -+ "data": {"set_id": {"set_id": self.src_ipport_ipset.vpp_id}}}, -+ {"is_src": True, "is_not": False, "type": ENTRY_PORT_RANGE, -+ "data": {"port_range": {"start": test_port, "end": test_port}}}, -+ ] -+ valid = [ -+ self.base_ip_packet(is_ip6) / TCP(sport=src_l4, dport=dst_l4) / random_payload(), -+ self.base_ip_packet(is_ip6) / TCP(sport=test_port, dport=dst_l4) / random_payload(), -+ self.base_ip_packet(is_ip6) / UDP(sport=test_port, dport=dst_l4) / random_payload(), -+ self.base_ip_packet(is_ip6, second_src_ip=True) / TCP(sport=test_port, dport=dst_l4) / random_payload(), -+ self.base_ip_packet(is_ip6, second_dst_ip=True) / TCP(sport=test_port, dport=dst_l4) / random_payload(), -+ ] -+ invalid = [ -+ self.base_ip_packet(is_ip6, second_src_ip=True) / TCP(sport=src_l4, dport=dst_l4) / random_payload(), -+ self.base_ip_packet(is_ip6) / UDP(sport=src_l4, dport=dst_l4) / random_payload(), -+ self.base_ip_packet(is_ip6) / TCP(sport=(src_l4+test_port)//2, dport=dst_l4) / random_payload(), -+ ] -+ self.do_test_one_rule([], matches, valid, invalid) -+ -+ for match in matches: -+ match['is_not'] = True -+ self.do_test_one_rule([], matches, invalid, valid) -+ -+ -+class TestCapoPolicies(BaseCapoTest): -+ """ Calico Policies tests """ -+ @classmethod -+ def setUpClass(self): -+ super(TestCapoPolicies, self).setUpClass() -+ -+ @classmethod -+ def tearDownClass(self): -+ super(TestCapoPolicies, self).tearDownClass() -+ -+ def setUp(self): -+ super(TestCapoPolicies, self).setUp() -+ -+ def tearDown(self): -+ super(TestCapoPolicies, self).tearDown() -+ -+ def tcp_dport_rule(self, port, action): -+ return VppCapoRule(self, is_v6=False, action=action, -+ filters=[VppCapoFilter(FILTER_TYPE_L4_PROTO, tcp_protocol, True)], -+ matches=[{"is_src": False, "is_not": False, "type": ENTRY_PORT_RANGE, -+ "data": {"port_range": {"start": port, "end": port}}}] -+ ) -+ -+ def test_inbound_outbound(self): -+ r = self.tcp_dport_rule(1000, ACTION_ALLOW) -+ r.add_vpp_config() -+ pin = VppCapoPolicy(self, [VppCapoPolicyItem(is_inbound=1, rule_id=r.vpp_id())]) -+ pout = VppCapoPolicy(self, [VppCapoPolicyItem(is_inbound=0, rule_id=r.vpp_id())]) -+ pin.add_vpp_config() -+ pout.add_vpp_config() -+ -+ matching = self.base_ip_packet() / TCP(sport=1, dport=1000) / random_payload() -+ not_matching = self.base_ip_packet() / TCP(sport=1, dport=2000) / random_payload() -+ -+ # out policy at src -+ self.configure_policies(self.pg0, [], [pout], []) -+ self.send_test_packets(self.pg0, self.pg1, [matching], [not_matching]) -+ -+ # policies configured at src + dst -+ self.configure_policies(self.pg1, [pin], [], []) -+ self.send_test_packets(self.pg0, self.pg1, [matching], [not_matching]) -+ -+ # policies configured at dst -+ self.configure_policies(self.pg0, [], [], []) -+ self.send_test_packets(self.pg0, self.pg1, [matching], [not_matching]) -+ -+ # no policies -+ self.configure_policies(self.pg1, [], [], []) -+ self.send_test_packets(self.pg0, self.pg1, [matching, not_matching], []) -+ -+ def test_default_verdict(self): -+ # If profiles only are configured (pass_id = 0), default is deny -+ # If there are policies + profiles (pass_id > 0), then default is to deny before -+ # evaluating profiles, unless a rule with a PASS target matches -+ rule1 = self.tcp_dport_rule(1000, ACTION_ALLOW) -+ rule2 = self.tcp_dport_rule(2000, ACTION_ALLOW) -+ rule3 = self.tcp_dport_rule(1000, ACTION_DENY) -+ rule4 = self.tcp_dport_rule(1000, ACTION_PASS) -+ rule1.add_vpp_config() -+ rule2.add_vpp_config() -+ rule3.add_vpp_config() -+ rule4.add_vpp_config() -+ policy1 = VppCapoPolicy(self, [VppCapoPolicyItem(is_inbound=1, rule_id=rule1.vpp_id())]) -+ policy2 = VppCapoPolicy(self, [VppCapoPolicyItem(is_inbound=1, rule_id=rule2.vpp_id())]) -+ policy3 = VppCapoPolicy(self, [VppCapoPolicyItem(is_inbound=1, rule_id=rule3.vpp_id())]) -+ policy4 = VppCapoPolicy(self, [VppCapoPolicyItem(is_inbound=1, rule_id=rule4.vpp_id())]) -+ policy5 = VppCapoPolicy(self, [ -+ VppCapoPolicyItem(is_inbound=1, rule_id=rule4.vpp_id()), -+ VppCapoPolicyItem(is_inbound=1, rule_id=rule3.vpp_id()), -+ ]) -+ policy1.add_vpp_config() -+ policy2.add_vpp_config() -+ policy3.add_vpp_config() -+ policy4.add_vpp_config() -+ policy5.add_vpp_config() -+ -+ # Test profile default deny: 1 allow rule, pass_id=0 -+ self.configure_policies(self.pg1, [], [], [policy1]) -+ passing = [self.base_ip_packet() / TCP(sport=1, dport=1000) / random_payload()] -+ dropped = [self.base_ip_packet() / TCP(sport=1, dport=2000) / random_payload()] -+ self.send_test_packets(self.pg0, self.pg1, passing, dropped) -+ -+ # Test policy default deny: 1 allow rule, pass_id=1 -+ self.configure_policies(self.pg1, [policy1], [], []) -+ self.send_test_packets(self.pg0, self.pg1, passing, dropped) -+ -+ # Test that profiles are not executed when policies are configured -+ # 1 allow policy, 1 allow profile, pass_id=1 -+ self.configure_policies(self.pg1, [policy1], [], [policy2]) -+ self.send_test_packets(self.pg0, self.pg1, passing, dropped) -+ -+ # Test that pass target does not evaluate further policies and jumps to profiles -+ # 1 pass policy, 1 deny policy, 1 allow profile, pass_id=2 -+ self.configure_policies(self.pg1, [policy4, policy3], [], [policy1]) -+ self.send_test_packets(self.pg0, self.pg1, passing, dropped) -+ -+ # Test that pass target does not evaluate further rules in the policy and jumps to profiles -+ # 1 policy w/ 1 pass rule & 1 deny rule, 1 deny profile, pass_id=1 -+ self.configure_policies(self.pg1, [policy5], [], [policy1]) -+ self.send_test_packets(self.pg0, self.pg1, passing, dropped) -+ -+ policy1.remove_vpp_config() -+ policy2.remove_vpp_config() -+ policy3.remove_vpp_config() -+ policy4.remove_vpp_config() -+ policy5.remove_vpp_config() -+ rule1.remove_vpp_config() -+ rule2.remove_vpp_config() -+ rule3.remove_vpp_config() -+ rule4.remove_vpp_config() -+ -+ def test_realistic_policy(self): -+ # Rule 1 allows ping from everywhere -+ rule1 = VppCapoRule(self, is_v6=False, action=ACTION_ALLOW, -+ filters = [ -+ VppCapoFilter(FILTER_TYPE_L4_PROTO, icmp_protocol, True), -+ VppCapoFilter(FILTER_TYPE_ICMP_TYPE, 8, True), -+ VppCapoFilter(FILTER_TYPE_ICMP_CODE, 0, True), -+ ], -+ matches = [], -+ ) -+ rule1.add_vpp_config() -+ # Rule 2 allows tcp dport 8080 from a single container -+ src_ipset = VppCapoIpset(self, IPSET_TYPE_NET, -+ [self.pg0.remote_ip4 + "/32", self.pg0.remote_ip6 + "/128"]) -+ src_ipset.add_vpp_config() -+ rule2 = VppCapoRule(self, is_v6=False, action=ACTION_ALLOW, -+ filters=[ -+ VppCapoFilter(FILTER_TYPE_L4_PROTO, tcp_protocol, True), -+ ], -+ matches = [ -+ {"is_src": True, "is_not": False, "type": ENTRY_IP_SET, -+ "data": {"set_id": {"set_id": src_ipset.vpp_id}}}, -+ {"is_src": False, "is_not": False, "type": ENTRY_PORT_RANGE, -+ "data": {"port_range": {"start": 8080, "end": 8080}}}, -+ ], -+ ) -+ rule2.add_vpp_config() -+ policy = VppCapoPolicy(self, [ -+ VppCapoPolicyItem(is_inbound=1, rule_id=rule1.vpp_id()), -+ VppCapoPolicyItem(is_inbound=1, rule_id=rule2.vpp_id()), -+ ]) -+ policy.add_vpp_config() -+ self.configure_policies(self.pg1, [policy], [], []) -+ -+ passing = [ -+ self.base_ip_packet() / ICMP(type=8), -+ self.base_ip_packet(second_src_ip=True) / ICMP(type=8), -+ self.base_ip_packet() / TCP(sport=1, dport=8080) / random_payload(), -+ ] -+ dropped = [ -+ self.base_ip_packet() / ICMP(type=3), -+ self.base_ip_packet(second_src_ip=True) / TCP(sport=1, dport=8080) / random_payload(), -+ self.base_ip_packet() / UDP(sport=1, dport=8080) / random_payload(), -+ self.base_ip_packet() / TCP(sport=1, dport=8081) / random_payload(), -+ ] -+ self.send_test_packets(self.pg0, self.pg1, passing, dropped) -+ # Cleanup -+ self.configure_policies(self.pg1, [], [], []) -+ policy.remove_vpp_config() -+ rule1.remove_vpp_config() -+ rule2.remove_vpp_config() -+ src_ipset.remove_vpp_config() --- -2.39.2 - diff --git a/vpplink/generated/patches/0005-partial-revert-arthur-gso.patch b/vpplink/generated/patches/0005-partial-revert-arthur-gso.patch deleted file mode 100644 index 03419ab23..000000000 --- a/vpplink/generated/patches/0005-partial-revert-arthur-gso.patch +++ /dev/null @@ -1,103 +0,0 @@ -From a5efb646c1e2575abe427f8f5f211a988464cde1 Mon Sep 17 00:00:00 2001 -From: Mohsin Kazmi -Date: Mon, 28 Oct 2024 16:44:11 +0000 -Subject: [PATCH] ip: add support for checksum in IP midchain - -Type: fix - -This is a temporary patch which should not be merged -in upstream VPP. -It only reverts partial support of the patch added by -https://gerrit.fd.io/r/c/vpp/+/32695 - -Today, virtual interfaces on egress does not support -checksum and GSO offload packets which are -encapsulated in tunnel. - -Signed-off-by: Mohsin Kazmi -Change-Id: Ib8c98bedc227419154aaaf1bebed46890ab69026 ---- - -diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c -index ff74b52..e18e688 100644 ---- a/src/vnet/ip/ip4_forward.c -+++ b/src/vnet/ip/ip4_forward.c -@@ -2225,6 +2225,9 @@ - adj0->ia_cfg_index); - - next[0] = next_index; -+ if (is_midchain) -+ vnet_calc_checksums_inline (vm, b[0], 1 /* is_ip4 */, -+ 0 /* is_ip6 */); - } - else - { -@@ -2247,6 +2250,9 @@ - &next_index, b[1], - adj1->ia_cfg_index); - next[1] = next_index; -+ if (is_midchain) -+ vnet_calc_checksums_inline (vm, b[1], 1 /* is_ip4 */, -+ 0 /* is_ip6 */); - } - else - { -@@ -2396,6 +2402,8 @@ - - if (is_midchain) - { -+ vnet_calc_checksums_inline (vm, b[0], 1 /* is_ip4 */, -+ 0 /* is_ip6 */); - /* Guess we are only writing on ipv4 header. */ - vnet_rewrite_one_header (adj0[0], ip0, sizeof (ip4_header_t)); - } -@@ -2499,6 +2507,8 @@ - - if (is_midchain) - { -+ vnet_calc_checksums_inline (vm, b[0], 1 /* is_ip4 */, -+ 0 /* is_ip6 */); - /* Guess we are only writing on ipv4 header. */ - vnet_rewrite_one_header (adj0[0], ip0, sizeof (ip4_header_t)); - } -diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c -index 31adc90..e697018 100644 ---- a/src/vnet/ip/ip6_forward.c -+++ b/src/vnet/ip/ip6_forward.c -@@ -1955,9 +1955,17 @@ - } - - if (is_midchain) -- /* Guess we are only writing on ipv6 header. */ -- vnet_rewrite_two_headers (adj0[0], adj1[0], ip0, ip1, -- sizeof (ip6_header_t)); -+ { -+ /* before we paint on the next header, update the L4 -+ * checksums if required, since there's no offload on a tunnel */ -+ vnet_calc_checksums_inline (vm, p0, 0 /* is_ip4 */, -+ 1 /* is_ip6 */); -+ vnet_calc_checksums_inline (vm, p1, 0 /* is_ip4 */, -+ 1 /* is_ip6 */); -+ /* Guess we are only writing on ipv6 header. */ -+ vnet_rewrite_two_headers (adj0[0], adj1[0], ip0, ip1, -+ sizeof (ip6_header_t)); -+ } - else - /* Guess we are only writing on simple Ethernet header. */ - vnet_rewrite_two_headers (adj0[0], adj1[0], -@@ -2085,8 +2093,13 @@ - adj0->ia_cfg_index); - - if (is_midchain) -- /* Guess we are only writing on ip6 header. */ -- vnet_rewrite_one_header (adj0[0], ip0, sizeof (ip6_header_t)); -+ { -+ vnet_calc_checksums_inline (vm, p0, 0 /* is_ip4 */, -+ 1 /* is_ip6 */); -+ /* Guess we are only writing on ip6 header. */ -+ vnet_rewrite_one_header (adj0[0], ip0, -+ sizeof (ip6_header_t)); -+ } - else - /* Guess we are only writing on simple Ethernet header. */ - vnet_rewrite_one_header (adj0[0], ip0, diff --git a/vpplink/generated/vpp_clone_current.sh b/vpplink/generated/vpp_clone_current.sh index bc2f3f49f..96f99c70a 100755 --- a/vpplink/generated/vpp_clone_current.sh +++ b/vpplink/generated/vpp_clone_current.sh @@ -145,10 +145,11 @@ git_cherry_pick refs/changes/07/43107/4 # 43107: vcl: fix fifo private vpp sh on git_cherry_pick refs/changes/14/43714/5 # 43714: session: fix handling of closed during migration | https://gerrit.fd.io/r/c/vpp/+/43714 git_cherry_pick refs/changes/39/43139/5 # 43139: udp: regrab connected session after transport clone | https://gerrit.fd.io/r/c/vpp/+/43139 git_cherry_pick refs/changes/23/43723/3 # 43723: session svm: fix session migrate attach data corruption | https://gerrit.fd.io/r/c/vpp/+/43723 +git_cherry_pick refs/changes/10/43710/12 # 43710: npol: Network Policies plugin | https://gerrit.fd.io/r/c/vpp/+/43710 # --------------- private plugins --------------- # Generated with 'git format-patch --zero-commit -o ./patches/ HEAD^^^' git_apply_private 0001-pbl-Port-based-balancer.patch git_apply_private 0002-cnat-WIP-no-k8s-maglev-from-pods.patch git_apply_private 0003-acl-acl-plugin-custom-policies.patch -git_apply_private 0004-capo-Calico-Policies-plugin.patch + diff --git a/vpplink/capo.go b/vpplink/npol.go similarity index 60% rename from vpplink/capo.go rename to vpplink/npol.go index e32a585d1..aca298cdb 100644 --- a/vpplink/capo.go +++ b/vpplink/npol.go @@ -19,51 +19,51 @@ import ( "fmt" "net" - "github.com/projectcalico/vpp-dataplane/v3/vpplink/generated/bindings/capo" + "github.com/projectcalico/vpp-dataplane/v3/vpplink/generated/bindings/npol" "github.com/projectcalico/vpp-dataplane/v3/vpplink/types" ) func (v *VppLink) IpsetCreate(ipsetType types.IpsetType) (setID uint32, err error) { - client := capo.NewServiceClient(v.GetConnection()) + client := npol.NewServiceClient(v.GetConnection()) - response, err := client.CapoIpsetCreate(v.GetContext(), &capo.CapoIpsetCreate{ - Type: capo.CapoIpsetType(ipsetType), + response, err := client.NpolIpsetCreate(v.GetContext(), &npol.NpolIpsetCreate{ + Type: npol.NpolIpsetType(ipsetType), }) if err != nil { - return 0, fmt.Errorf("capoIpsetCreate failed: %w", err) + return 0, fmt.Errorf("npolIpsetCreate failed: %w", err) } return response.SetID, nil } func (v *VppLink) IpsetDelete(ipsetID uint32) error { - client := capo.NewServiceClient(v.GetConnection()) + client := npol.NewServiceClient(v.GetConnection()) - _, err := client.CapoIpsetDelete(v.GetContext(), &capo.CapoIpsetDelete{ + _, err := client.NpolIpsetDelete(v.GetContext(), &npol.NpolIpsetDelete{ SetID: ipsetID, }) if err != nil { - return fmt.Errorf("capoIpsetDelete failed: %w", err) + return fmt.Errorf("npolIpsetDelete failed: %w", err) } return nil } -func (v *VppLink) addDelIpsetMembers(ipsetID uint32, isAdd bool, members []capo.CapoIpsetMember) error { - client := capo.NewServiceClient(v.GetConnection()) +func (v *VppLink) addDelIpsetMembers(ipsetID uint32, isAdd bool, members []npol.NpolIpsetMember) error { + client := npol.NewServiceClient(v.GetConnection()) - _, err := client.CapoIpsetAddDelMembers(v.GetContext(), &capo.CapoIpsetAddDelMembers{ + _, err := client.NpolIpsetAddDelMembers(v.GetContext(), &npol.NpolIpsetAddDelMembers{ SetID: ipsetID, IsAdd: isAdd, Len: uint32(len(members)), Members: members, }) if err != nil { - return fmt.Errorf("capoIpsetAddDelMembers failed: %w", err) + return fmt.Errorf("npolIpsetAddDelMembers failed: %w", err) } return nil } func (v *VppLink) addDelIpsetIPMembers(ipsetID uint32, isAdd bool, members []net.IP) (err error) { - unions := make([]capo.CapoIpsetMember, len(members)) + unions := make([]npol.NpolIpsetMember, len(members)) for i, m := range members { unions[i].Val.SetAddress(types.ToVppAddress(m)) } @@ -79,7 +79,7 @@ func (v *VppLink) DelIpsetIPMembers(ipsetID uint32, members []net.IP) (err error } func (v *VppLink) addDelIpsetNetMembers(ipsetID uint32, isAdd bool, members []*net.IPNet) (err error) { - unions := make([]capo.CapoIpsetMember, len(members)) + unions := make([]npol.NpolIpsetMember, len(members)) for i, m := range members { unions[i].Val.SetPrefix(types.ToVppPrefix(m)) } @@ -95,9 +95,9 @@ func (v *VppLink) DelIpsetNetMembers(ipsetID uint32, members []*net.IPNet) (err } func (v *VppLink) addDelIpsetIPPortMembers(ipsetID uint32, isAdd bool, members []types.IPPort) (err error) { - unions := make([]capo.CapoIpsetMember, len(members)) + unions := make([]npol.NpolIpsetMember, len(members)) for i, m := range members { - unions[i].Val.SetTuple(capo.CapoThreeTuple{ + unions[i].Val.SetTuple(npol.NpolThreeTuple{ Address: types.ToVppAddress(m.Addr), L4Proto: m.L4Proto, Port: m.Port, @@ -115,81 +115,81 @@ func (v *VppLink) DelIpsetIPPortMembers(ipsetID uint32, members []types.IPPort) } func (v *VppLink) RuleCreate(rule *types.Rule) (ruleID uint32, err error) { - client := capo.NewServiceClient(v.GetConnection()) + client := npol.NewServiceClient(v.GetConnection()) - response, err := client.CapoRuleCreate(v.GetContext(), &capo.CapoRuleCreate{ - Rule: types.ToCapoRule(rule), + response, err := client.NpolRuleCreate(v.GetContext(), &npol.NpolRuleCreate{ + Rule: types.ToNpolRule(rule), }) if err != nil { - return 0, fmt.Errorf("capoRuleCreate failed: %w", err) + return 0, fmt.Errorf("npolRuleCreate failed: %w", err) } return response.RuleID, nil } func (v *VppLink) RuleUpdate(ruleID uint32, rule *types.Rule) error { - client := capo.NewServiceClient(v.GetConnection()) + client := npol.NewServiceClient(v.GetConnection()) - _, err := client.CapoRuleUpdate(v.GetContext(), &capo.CapoRuleUpdate{ + _, err := client.NpolRuleUpdate(v.GetContext(), &npol.NpolRuleUpdate{ RuleID: ruleID, - Rule: types.ToCapoRule(rule), + Rule: types.ToNpolRule(rule), }) if err != nil { - return fmt.Errorf("capoRuleUpdate failed: %w", err) + return fmt.Errorf("npolRuleUpdate failed: %w", err) } return nil } func (v *VppLink) RuleDelete(ruleID uint32) error { - client := capo.NewServiceClient(v.GetConnection()) + client := npol.NewServiceClient(v.GetConnection()) - _, err := client.CapoRuleDelete(v.GetContext(), &capo.CapoRuleDelete{ + _, err := client.NpolRuleDelete(v.GetContext(), &npol.NpolRuleDelete{ RuleID: ruleID, }) if err != nil { - return fmt.Errorf("capoRuleDelete failed: %w", err) + return fmt.Errorf("npolRuleDelete failed: %w", err) } return nil } func (v *VppLink) PolicyCreate(policy *types.Policy) (policyID uint32, err error) { - client := capo.NewServiceClient(v.GetConnection()) + client := npol.NewServiceClient(v.GetConnection()) - response, err := client.CapoPolicyCreate(v.GetContext(), &capo.CapoPolicyCreate{ - Rules: types.ToCapoPolicy(policy), + response, err := client.NpolPolicyCreate(v.GetContext(), &npol.NpolPolicyCreate{ + Rules: types.ToNpolPolicy(policy), }) if err != nil { - return 0, fmt.Errorf("capoPolicyCreate failed: %w", err) + return 0, fmt.Errorf("npolPolicyCreate failed: %w", err) } return response.PolicyID, nil } func (v *VppLink) PolicyUpdate(policyID uint32, policy *types.Policy) error { - client := capo.NewServiceClient(v.GetConnection()) + client := npol.NewServiceClient(v.GetConnection()) - _, err := client.CapoPolicyUpdate(v.GetContext(), &capo.CapoPolicyUpdate{ + _, err := client.NpolPolicyUpdate(v.GetContext(), &npol.NpolPolicyUpdate{ PolicyID: policyID, - Rules: types.ToCapoPolicy(policy), + Rules: types.ToNpolPolicy(policy), }) if err != nil { - return fmt.Errorf("capoPolicyUpdate failed: %w", err) + return fmt.Errorf("npolPolicyUpdate failed: %w", err) } return nil } func (v *VppLink) PolicyDelete(policyID uint32) error { - client := capo.NewServiceClient(v.GetConnection()) + client := npol.NewServiceClient(v.GetConnection()) - _, err := client.CapoPolicyDelete(v.GetContext(), &capo.CapoPolicyDelete{ + _, err := client.NpolPolicyDelete(v.GetContext(), &npol.NpolPolicyDelete{ PolicyID: policyID, }) if err != nil { - return fmt.Errorf("capoPolicyDelete failed: %w", err) + return fmt.Errorf("npolPolicyDelete failed: %w", err) } return nil } func (v *VppLink) ConfigurePolicies(swIfIndex uint32, conf *types.InterfaceConfig, invertRxTx uint8) error { - client := capo.NewServiceClient(v.GetConnection()) + client := npol.NewServiceClient(v.GetConnection()) // In the calico agent, policies are expressed from the point of view of PODs // in VPP this is reversed @@ -199,16 +199,20 @@ func (v *VppLink) ConfigurePolicies(swIfIndex uint32, conf *types.InterfaceConfi ids := append(rxPolicyIDs, txPolicyIDs...) ids = append(ids, profileIDs...) - _, err := client.CapoConfigurePolicies(v.GetContext(), &capo.CapoConfigurePolicies{ - SwIfIndex: swIfIndex, - NumRxPolicies: uint32(len(rxPolicyIDs)), - NumTxPolicies: uint32(len(txPolicyIDs)), - TotalIds: uint32(len(rxPolicyIDs) + len(txPolicyIDs) + len(profileIDs)), - PolicyIds: ids, - InvertRxTx: invertRxTx, + _, err := client.NpolConfigurePolicies(v.GetContext(), &npol.NpolConfigurePolicies{ + SwIfIndex: swIfIndex, + NumRxPolicies: uint32(len(rxPolicyIDs)), + NumTxPolicies: uint32(len(txPolicyIDs)), + TotalIds: uint32(len(rxPolicyIDs) + len(txPolicyIDs) + len(profileIDs)), + PolicyIds: ids, + InvertRxTx: invertRxTx, + PolicyDefaultRx: conf.PolicyDefaultRx, + PolicyDefaultTx: conf.PolicyDefaultTx, + ProfileDefaultRx: conf.ProfileDefaultRx, + ProfileDefaultTx: conf.ProfileDefaultTx, }) if err != nil { - return fmt.Errorf("capoConfigurePolicies failed: %w", err) + return fmt.Errorf("npolConfigurePolicies failed: %w", err) } return nil } diff --git a/vpplink/types/capo.go b/vpplink/types/npol.go similarity index 71% rename from vpplink/types/capo.go rename to vpplink/types/npol.go index eddff2be1..4ccb84614 100644 --- a/vpplink/types/capo.go +++ b/vpplink/types/npol.go @@ -20,8 +20,7 @@ import ( "net" "reflect" - "github.com/projectcalico/vpp-dataplane/v3/vpplink/generated/bindings/capo" - "github.com/projectcalico/vpp-dataplane/v3/vpplink/generated/bindings/ip_types" + "github.com/projectcalico/vpp-dataplane/v3/vpplink/generated/bindings/npol" ) const InvalidID uint32 = ^uint32(0) @@ -29,9 +28,9 @@ const InvalidID uint32 = ^uint32(0) type IpsetType uint8 const ( - IpsetTypeIP IpsetType = IpsetType(capo.CAPO_IP) - IpsetTypeIPPort IpsetType = IpsetType(capo.CAPO_IP_AND_PORT) - IpsetTypeNet IpsetType = IpsetType(capo.CAPO_NET) + IpsetTypeIP IpsetType = IpsetType(npol.NPOL_IP) + IpsetTypeIPPort IpsetType = IpsetType(npol.NPOL_IP_AND_PORT) + IpsetTypeNet IpsetType = IpsetType(npol.NPOL_NET) ) func (i IpsetType) String() string { @@ -55,10 +54,10 @@ type IPPort struct { type RuleAction uint8 const ( - ActionAllow RuleAction = RuleAction(capo.CAPO_ALLOW) - ActionDeny RuleAction = RuleAction(capo.CAPO_DENY) - ActionLog RuleAction = RuleAction(capo.CAPO_LOG) - ActionPass RuleAction = RuleAction(capo.CAPO_PASS) + ActionAllow RuleAction = RuleAction(npol.NPOL_ALLOW) + ActionDeny RuleAction = RuleAction(npol.NPOL_DENY) + ActionLog RuleAction = RuleAction(npol.NPOL_LOG) + ActionPass RuleAction = RuleAction(npol.NPOL_PASS) ) func (r RuleAction) String() string { @@ -88,24 +87,24 @@ func (pr PortRange) String() string { } } -type CapoFilterType uint8 +type NpolFilterType uint8 const ( - CapoFilterTypeNone CapoFilterType = CapoFilterType(capo.CAPO_RULE_FILTER_NONE_TYPE) - CapoFilterICMPType CapoFilterType = CapoFilterType(capo.CAPO_RULE_FILTER_ICMP_TYPE) - CapoFilterICMPCode CapoFilterType = CapoFilterType(capo.CAPO_RULE_FILTER_ICMP_CODE) - CapoFilterProto CapoFilterType = CapoFilterType(capo.CAPO_RULE_FILTER_L4_PROTO) + NpolFilterTypeNone NpolFilterType = NpolFilterType(npol.NPOL_RULE_FILTER_NONE_TYPE) + NpolFilterICMPType NpolFilterType = NpolFilterType(npol.NPOL_RULE_FILTER_ICMP_TYPE) + NpolFilterICMPCode NpolFilterType = NpolFilterType(npol.NPOL_RULE_FILTER_ICMP_CODE) + NpolFilterProto NpolFilterType = NpolFilterType(npol.NPOL_RULE_FILTER_L4_PROTO) ) -func (ft CapoFilterType) String() string { +func (ft NpolFilterType) String() string { switch ft { - case CapoFilterTypeNone: + case NpolFilterTypeNone: return "none" - case CapoFilterICMPType: + case NpolFilterICMPType: return "icmp-type" - case CapoFilterICMPCode: + case NpolFilterICMPCode: return "icmp-code" - case CapoFilterProto: + case NpolFilterProto: return "proto" } return "unknown-filter-type" @@ -113,7 +112,7 @@ func (ft CapoFilterType) String() string { type RuleFilter struct { ShouldMatch bool - Type CapoFilterType + Type NpolFilterType Value int } @@ -126,9 +125,8 @@ func (f RuleFilter) String() string { } type Rule struct { - Action RuleAction - AddressFamily int - Filters []RuleFilter + Action RuleAction + Filters []RuleFilter DstNet []net.IPNet DstNotNet []net.IPNet @@ -156,7 +154,6 @@ type Rule struct { func (r *Rule) DeepCopy() *Rule { rule := &Rule{ Action: r.Action, - AddressFamily: r.AddressFamily, Filters: make([]RuleFilter, len(r.Filters)), DstNet: make([]net.IPNet, len(r.DstNet)), DstNotNet: make([]net.IPNet, len(r.DstNotNet)), @@ -326,6 +323,10 @@ type InterfaceConfig struct { IngressPolicyIDs []uint32 EgressPolicyIDs []uint32 ProfileIDs []uint32 + PolicyDefaultRx npol.NpolPolicyDefault + PolicyDefaultTx npol.NpolPolicyDefault + ProfileDefaultRx npol.NpolPolicyDefault + ProfileDefaultTx npol.NpolPolicyDefault } func NewInterfaceConfig() *InterfaceConfig { @@ -333,13 +334,17 @@ func NewInterfaceConfig() *InterfaceConfig { IngressPolicyIDs: make([]uint32, 0), EgressPolicyIDs: make([]uint32, 0), ProfileIDs: make([]uint32, 0), + PolicyDefaultRx: npol.NPOL_DEFAULT_ALLOW, + PolicyDefaultTx: npol.NPOL_DEFAULT_ALLOW, + ProfileDefaultRx: npol.NPOL_DEFAULT_DENY, + ProfileDefaultTx: npol.NPOL_DEFAULT_DENY, } } -func toCapoFilter(f *RuleFilter) capo.CapoRuleFilter { - return capo.CapoRuleFilter{ +func toNpolFilter(f *RuleFilter) npol.NpolRuleFilter { + return npol.NpolRuleFilter{ Value: uint32(f.Value), - Type: capo.CapoRuleFilterType(f.Type), + Type: npol.NpolRuleFilterType(f.Type), ShouldMatch: boolToU8(f.ShouldMatch), } } @@ -355,131 +360,129 @@ func (i *IPPort) Equal(j *IPPort) bool { return i.Port == j.Port && i.L4Proto == j.L4Proto && i.Addr.Equal(j.Addr) } -func toCapoPortRange(pr PortRange) capo.CapoPortRange { - return capo.CapoPortRange{ +func toNpolPortRange(pr PortRange) npol.NpolPortRange { + return npol.NpolPortRange{ Start: pr.First, End: pr.Last, } } -func ToCapoRule(r *Rule) (cr capo.CapoRule) { - var filters [3]capo.CapoRuleFilter +func ToNpolRule(r *Rule) (cr npol.NpolRule) { + var filters [3]npol.NpolRuleFilter for i, f := range r.Filters { if i == 3 { break } - filters[i] = toCapoFilter(&f) + filters[i] = toNpolFilter(&f) } - cr = capo.CapoRule{ - Action: capo.CapoRuleAction(r.Action), - Af: ip_types.AddressFamily(r.AddressFamily), - + cr = npol.NpolRule{ + Action: npol.NpolRuleAction(r.Action), Filters: filters, } for _, n := range r.DstNet { - entry := capo.CapoRuleEntry{IsSrc: false, IsNot: false, Type: capo.CAPO_CIDR} + entry := npol.NpolRuleEntry{IsSrc: false, IsNot: false, Type: npol.NPOL_CIDR} entry.Data.SetCidr(ToVppPrefix(&n)) cr.Matches = append(cr.Matches, entry) } for _, n := range r.DstNotNet { - entry := capo.CapoRuleEntry{IsSrc: false, IsNot: true, Type: capo.CAPO_CIDR} + entry := npol.NpolRuleEntry{IsSrc: false, IsNot: true, Type: npol.NPOL_CIDR} entry.Data.SetCidr(ToVppPrefix(&n)) cr.Matches = append(cr.Matches, entry) } for _, n := range r.SrcNet { - entry := capo.CapoRuleEntry{IsSrc: true, IsNot: false, Type: capo.CAPO_CIDR} + entry := npol.NpolRuleEntry{IsSrc: true, IsNot: false, Type: npol.NPOL_CIDR} entry.Data.SetCidr(ToVppPrefix(&n)) cr.Matches = append(cr.Matches, entry) } for _, n := range r.SrcNotNet { - entry := capo.CapoRuleEntry{IsSrc: true, IsNot: true, Type: capo.CAPO_CIDR} + entry := npol.NpolRuleEntry{IsSrc: true, IsNot: true, Type: npol.NPOL_CIDR} entry.Data.SetCidr(ToVppPrefix(&n)) cr.Matches = append(cr.Matches, entry) } for _, pr := range r.DstPortRange { - entry := capo.CapoRuleEntry{IsSrc: false, IsNot: false, Type: capo.CAPO_PORT_RANGE} - entry.Data.SetPortRange(toCapoPortRange(pr)) + entry := npol.NpolRuleEntry{IsSrc: false, IsNot: false, Type: npol.NPOL_PORT_RANGE} + entry.Data.SetPortRange(toNpolPortRange(pr)) cr.Matches = append(cr.Matches, entry) } for _, pr := range r.DstNotPortRange { - entry := capo.CapoRuleEntry{IsSrc: false, IsNot: true, Type: capo.CAPO_PORT_RANGE} - entry.Data.SetPortRange(toCapoPortRange(pr)) + entry := npol.NpolRuleEntry{IsSrc: false, IsNot: true, Type: npol.NPOL_PORT_RANGE} + entry.Data.SetPortRange(toNpolPortRange(pr)) cr.Matches = append(cr.Matches, entry) } for _, pr := range r.SrcPortRange { - entry := capo.CapoRuleEntry{IsSrc: true, IsNot: false, Type: capo.CAPO_PORT_RANGE} - entry.Data.SetPortRange(toCapoPortRange(pr)) + entry := npol.NpolRuleEntry{IsSrc: true, IsNot: false, Type: npol.NPOL_PORT_RANGE} + entry.Data.SetPortRange(toNpolPortRange(pr)) cr.Matches = append(cr.Matches, entry) } for _, pr := range r.SrcNotPortRange { - entry := capo.CapoRuleEntry{IsSrc: true, IsNot: true, Type: capo.CAPO_PORT_RANGE} - entry.Data.SetPortRange(toCapoPortRange(pr)) + entry := npol.NpolRuleEntry{IsSrc: true, IsNot: true, Type: npol.NPOL_PORT_RANGE} + entry.Data.SetPortRange(toNpolPortRange(pr)) cr.Matches = append(cr.Matches, entry) } for _, id := range r.DstIPPortIPSet { - entry := capo.CapoRuleEntry{IsSrc: false, IsNot: false, Type: capo.CAPO_PORT_IP_SET} - entry.Data.SetSetID(capo.CapoEntrySetID{SetID: id}) + entry := npol.NpolRuleEntry{IsSrc: false, IsNot: false, Type: npol.NPOL_PORT_IP_SET} + entry.Data.SetSetID(npol.NpolEntrySetID{SetID: id}) cr.Matches = append(cr.Matches, entry) } for _, id := range r.DstNotIPPortIPSet { - entry := capo.CapoRuleEntry{IsSrc: false, IsNot: true, Type: capo.CAPO_PORT_IP_SET} - entry.Data.SetSetID(capo.CapoEntrySetID{SetID: id}) + entry := npol.NpolRuleEntry{IsSrc: false, IsNot: true, Type: npol.NPOL_PORT_IP_SET} + entry.Data.SetSetID(npol.NpolEntrySetID{SetID: id}) cr.Matches = append(cr.Matches, entry) } for _, id := range r.SrcIPPortIPSet { - entry := capo.CapoRuleEntry{IsSrc: true, IsNot: false, Type: capo.CAPO_PORT_IP_SET} - entry.Data.SetSetID(capo.CapoEntrySetID{SetID: id}) + entry := npol.NpolRuleEntry{IsSrc: true, IsNot: false, Type: npol.NPOL_PORT_IP_SET} + entry.Data.SetSetID(npol.NpolEntrySetID{SetID: id}) cr.Matches = append(cr.Matches, entry) } for _, id := range r.SrcNotIPPortIPSet { - entry := capo.CapoRuleEntry{IsSrc: true, IsNot: true, Type: capo.CAPO_PORT_IP_SET} - entry.Data.SetSetID(capo.CapoEntrySetID{SetID: id}) + entry := npol.NpolRuleEntry{IsSrc: true, IsNot: true, Type: npol.NPOL_PORT_IP_SET} + entry.Data.SetSetID(npol.NpolEntrySetID{SetID: id}) cr.Matches = append(cr.Matches, entry) } for _, id := range r.DstIPSet { - entry := capo.CapoRuleEntry{IsSrc: false, IsNot: false, Type: capo.CAPO_IP_SET} - entry.Data.SetSetID(capo.CapoEntrySetID{SetID: id}) + entry := npol.NpolRuleEntry{IsSrc: false, IsNot: false, Type: npol.NPOL_IP_SET} + entry.Data.SetSetID(npol.NpolEntrySetID{SetID: id}) cr.Matches = append(cr.Matches, entry) } for _, id := range r.DstNotIPSet { - entry := capo.CapoRuleEntry{IsSrc: false, IsNot: true, Type: capo.CAPO_IP_SET} - entry.Data.SetSetID(capo.CapoEntrySetID{SetID: id}) + entry := npol.NpolRuleEntry{IsSrc: false, IsNot: true, Type: npol.NPOL_IP_SET} + entry.Data.SetSetID(npol.NpolEntrySetID{SetID: id}) cr.Matches = append(cr.Matches, entry) } for _, id := range r.SrcIPSet { - entry := capo.CapoRuleEntry{IsSrc: true, IsNot: false, Type: capo.CAPO_IP_SET} - entry.Data.SetSetID(capo.CapoEntrySetID{SetID: id}) + entry := npol.NpolRuleEntry{IsSrc: true, IsNot: false, Type: npol.NPOL_IP_SET} + entry.Data.SetSetID(npol.NpolEntrySetID{SetID: id}) cr.Matches = append(cr.Matches, entry) } for _, id := range r.SrcNotIPSet { - entry := capo.CapoRuleEntry{IsSrc: true, IsNot: true, Type: capo.CAPO_IP_SET} - entry.Data.SetSetID(capo.CapoEntrySetID{SetID: id}) + entry := npol.NpolRuleEntry{IsSrc: true, IsNot: true, Type: npol.NPOL_IP_SET} + entry.Data.SetSetID(npol.NpolEntrySetID{SetID: id}) cr.Matches = append(cr.Matches, entry) } for _, id := range r.DstIPPortSet { - entry := capo.CapoRuleEntry{IsSrc: false, IsNot: false, Type: capo.CAPO_PORT_IP_SET} - entry.Data.SetSetID(capo.CapoEntrySetID{SetID: id}) + entry := npol.NpolRuleEntry{IsSrc: false, IsNot: false, Type: npol.NPOL_PORT_IP_SET} + entry.Data.SetSetID(npol.NpolEntrySetID{SetID: id}) cr.Matches = append(cr.Matches, entry) } return cr } -func ToCapoPolicy(p *Policy) (items []capo.CapoPolicyItem) { - items = make([]capo.CapoPolicyItem, 0, len(p.InboundRuleIDs)+len(p.OutboundRuleIDs)) +func ToNpolPolicy(p *Policy) (items []npol.NpolPolicyItem) { + items = make([]npol.NpolPolicyItem, 0, len(p.InboundRuleIDs)+len(p.OutboundRuleIDs)) for _, rid := range p.InboundRuleIDs { - items = append(items, capo.CapoPolicyItem{ + items = append(items, npol.NpolPolicyItem{ IsInbound: false, // Calico policies are expressed from the point of view of PODs // in VPP this is reversed RuleID: rid, }) } for _, rid := range p.OutboundRuleIDs { - items = append(items, capo.CapoPolicyItem{ + items = append(items, npol.NpolPolicyItem{ IsInbound: true, // Calico policies are expressed from the point of view of PODs // in VPP this is reversed RuleID: rid,