Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ICMP support in ACNP and ANP #3470

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,567 changes: 1,293 additions & 274 deletions build/yamls/antrea-aks.yml

Large diffs are not rendered by default.

1,567 changes: 1,293 additions & 274 deletions build/yamls/antrea-eks.yml

Large diffs are not rendered by default.

1,567 changes: 1,293 additions & 274 deletions build/yamls/antrea-gke.yml

Large diffs are not rendered by default.

1,567 changes: 1,293 additions & 274 deletions build/yamls/antrea-ipsec.yml

Large diffs are not rendered by default.

1,567 changes: 1,293 additions & 274 deletions build/yamls/antrea-kind.yml

Large diffs are not rendered by default.

1,567 changes: 1,293 additions & 274 deletions build/yamls/antrea.yml

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions build/yamls/base/controller.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ webhooks:
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["crd.antrea.io"]
apiVersions: ["v1alpha1"]
apiVersions: ["v1alpha2", "v1alpha1"]
resources: ["clusternetworkpolicies"]
scope: "Cluster"
admissionReviewVersions: ["v1", "v1beta1"]
Expand All @@ -117,7 +117,7 @@ webhooks:
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["crd.antrea.io"]
apiVersions: ["v1alpha1"]
apiVersions: ["v1alpha2", "v1alpha1"]
resources: ["networkpolicies"]
scope: "Namespaced"
admissionReviewVersions: ["v1", "v1beta1"]
Expand Down
1,239 changes: 1,117 additions & 122 deletions build/yamls/base/crds.yml

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions cmd/antrea-controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ var allowedPaths = []string{
"/validate/egress",
"/validate/ippool",
"/convert/clustergroup",
"/convert/clusternetworkpolicy",
"/convert/networkpolicy",
}

// run starts Antrea Controller with the given options and waits for termination signal.
Expand All @@ -115,9 +117,9 @@ func run(o *Options) error {
serviceInformer := informerFactory.Core().V1().Services()
networkPolicyInformer := informerFactory.Networking().V1().NetworkPolicies()
nodeInformer := informerFactory.Core().V1().Nodes()
cnpInformer := crdInformerFactory.Crd().V1alpha1().ClusterNetworkPolicies()
cnpInformer := crdInformerFactory.Crd().V1alpha2().ClusterNetworkPolicies()
eeInformer := crdInformerFactory.Crd().V1alpha2().ExternalEntities()
anpInformer := crdInformerFactory.Crd().V1alpha1().NetworkPolicies()
anpInformer := crdInformerFactory.Crd().V1alpha2().NetworkPolicies()
tierInformer := crdInformerFactory.Crd().V1alpha1().Tiers()
tfInformer := crdInformerFactory.Crd().V1alpha1().Traceflows()
cgInformer := crdInformerFactory.Crd().V1alpha3().ClusterGroups()
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ module antrea.io/antrea
go 1.17

require (
antrea.io/libOpenflow v0.6.1
antrea.io/ofnet v0.2.3
antrea.io/libOpenflow v0.6.2
antrea.io/ofnet v0.5.2
github.com/Mellanox/sriovnet v1.0.2
github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331
github.com/Microsoft/hcsshim v0.8.9
Expand Down
9 changes: 4 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
antrea.io/libOpenflow v0.5.2/go.mod h1:CzEJZxDNAupiGxeL5VOw92PsxfyvehEAvE3PiC6gr8o=
antrea.io/libOpenflow v0.6.1 h1:RjYKz8WJTjerqu/J9ASygv+oF7Bu0jhIiqLnIIyZPhs=
antrea.io/libOpenflow v0.6.1/go.mod h1:CzEJZxDNAupiGxeL5VOw92PsxfyvehEAvE3PiC6gr8o=
antrea.io/ofnet v0.2.3 h1:wxXOqWaT5swtn9Ly6hV7pqvIgfmrr3aQfCGVQqHykr4=
antrea.io/ofnet v0.2.3/go.mod h1:jW4ICTvGjLO+Qr6GG/Glmjy34k6k/TfVlQhOm76UH84=
antrea.io/libOpenflow v0.6.2 h1:1JMSJ7Lp7yOhKybHey9VDtRI6JuIgkhUWJBX5GIFY9I=
antrea.io/libOpenflow v0.6.2/go.mod h1:CzEJZxDNAupiGxeL5VOw92PsxfyvehEAvE3PiC6gr8o=
antrea.io/ofnet v0.5.2 h1:xv5ncYeOudJPjdH1SjFoYoflTgQ2XX5Rg1Arva7ittg=
antrea.io/ofnet v0.5.2/go.mod h1:8TJVF6MLe9/gZ/KbhGUvULs9/TxssepEaYEe+o1SEgs=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
Expand Down
142 changes: 119 additions & 23 deletions pkg/agent/openflow/network_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ var (
MatchTCPv6SrcPort = types.NewMatchKey(binding.ProtocolTCPv6, types.L4PortAddr, "tp_src")
MatchUDPSrcPort = types.NewMatchKey(binding.ProtocolUDP, types.L4PortAddr, "tp_src")
MatchUDPv6SrcPort = types.NewMatchKey(binding.ProtocolUDPv6, types.L4PortAddr, "tp_src")
MatchICMPType = types.NewMatchKey(binding.ProtocolICMP, types.ICMPAddr, "icmp_type")
MatchICMPCode = types.NewMatchKey(binding.ProtocolICMP, types.ICMPAddr, "icmp_code")
MatchICMPv6Type = types.NewMatchKey(binding.ProtocolICMPv6, types.ICMPAddr, "icmpv6_type")
MatchICMPv6Code = types.NewMatchKey(binding.ProtocolICMPv6, types.ICMPAddr, "icmpv6_code")
MatchServiceGroupID = types.NewMatchKey(binding.ProtocolIP, types.ServiceGroupIDAddr, "reg7[0..31]")
Unsupported = types.NewMatchKey(binding.ProtocolIP, types.UnSupported, "unknown")

Expand Down Expand Up @@ -203,13 +207,17 @@ func newConjunctionNotFound(conjunctionID uint32) *ConjunctionNotFound {
type conjunctiveMatch struct {
tableID uint8
priority *uint16
matchPairs []matchPair
}

type matchPair struct {
matchKey *types.MatchKey
matchValue interface{}
}

func (m *conjunctiveMatch) generateGlobalMapKey() string {
var valueStr, priorityStr string
func (m *matchPair) KeyString() string {
matchType := m.matchKey
var valueStr string
switch v := m.matchValue.(type) {
case net.IP:
// Use the unique format "x.x.x.x/xx" for IP address and IP net, to avoid generating two different global map
Expand Down Expand Up @@ -245,16 +253,28 @@ func (m *conjunctiveMatch) generateGlobalMapKey() string {
// To normalize the key, set full mask while a single port is provided.
valueStr = fmt.Sprintf("%d/65535", bitRange.Value)
}
case *int32:
// This cases include the matchValue is ICMPType or ICMPCode.
valueStr = fmt.Sprintf("%d", *m.matchValue.(*int32))
default:
// The default cases include the matchValue is an ofport Number.
valueStr = fmt.Sprintf("%s", m.matchValue)
}
return fmt.Sprintf("%v=%s", matchType, valueStr)
}

func (m *conjunctiveMatch) generateGlobalMapKey() string {
var priorityStr string
var matchPairStrList []string
for _, eachMatchPair := range m.matchPairs {
matchPairStrList = append(matchPairStrList, eachMatchPair.KeyString())
}
if m.priority == nil {
priorityStr = strconv.Itoa(int(priorityNormal))
} else {
priorityStr = strconv.Itoa(int(*m.priority))
}
return fmt.Sprintf("table:%d,priority:%s,type:%v,value:%s", m.tableID, priorityStr, matchType, valueStr)
return fmt.Sprintf("table:%d,priority:%s,matchPair:%s", m.tableID, priorityStr, strings.Join(matchPairStrList, ","))
}

// changeType is generally used to describe the change type of a conjMatchFlowContext. It is also used in "flowChange"
Expand Down Expand Up @@ -329,7 +349,7 @@ func (ctx *conjMatchFlowContext) createOrUpdateConjunctiveMatchFlow(actions []*c

// Create the conjunctive match flow entry. The actions here should not be empty for either add or update case.
// The expected operation for a new Openflow entry should be "insertion".
flow := ctx.client.conjunctiveMatchFlow(ctx.tableID, ctx.matchKey, ctx.matchValue, ctx.priority, actions)
flow := ctx.client.conjunctiveMatchFlow(ctx.tableID, ctx.matchPairs, ctx.priority, actions)
return &flowChange{
flow: flow,
changeType: insertion,
Expand Down Expand Up @@ -616,7 +636,7 @@ func (c *clause) addConjunctiveMatchFlow(client *client, match *conjunctiveMatch
// Generate the default drop flow if dropTable is not nil and the default drop flow is not set yet.
if c.dropTable != nil && context.dropFlow == nil {
dropFlow = &flowChange{
flow: context.client.defaultDropFlow(c.dropTable, match.matchKey, match.matchValue),
flow: context.client.defaultDropFlow(c.dropTable, match.matchPairs),
changeType: insertion,
}
}
Expand Down Expand Up @@ -655,8 +675,7 @@ func generateAddressConjMatch(ruleTableID uint8, addr types.Address, addrType ty
matchValue := addr.GetValue()
match := &conjunctiveMatch{
tableID: ruleTableID,
matchKey: matchKey,
matchValue: matchValue,
matchPairs: []matchPair{{matchKey: matchKey, matchValue: matchValue}},
priority: priority,
}
return match
Expand Down Expand Up @@ -710,22 +729,99 @@ func getServiceMatchType(protocol *v1beta2.Protocol, ipv4Enabled, ipv6Enabled, m
return matchKeys
}

func generateServicePortConjMatches(ruleTableID uint8, service v1beta2.Service, priority *uint16, ipv4Enabled, ipv6Enabled, matchSrc bool) []*conjunctiveMatch {
matchKeys := getServiceMatchType(service.Protocol, ipv4Enabled, ipv6Enabled, matchSrc)
ovsBitRanges := serviceToBitRanges(service)
func generateServiceConjMatches(ruleTableID uint8, service v1beta2.Service, priority *uint16, ipv4Enabled, ipv6Enabled, matchSrc bool) []*conjunctiveMatch {
var matches []*conjunctiveMatch
for _, matchKey := range matchKeys {
conjMatchesMatchPairs := getServiceMatchPairs(service, ipv4Enabled, ipv6Enabled, matchSrc)
for _, conjMatchMatchPairs := range conjMatchesMatchPairs {
matches = append(matches,
&conjunctiveMatch{
tableID: ruleTableID,
matchPairs: conjMatchMatchPairs,
priority: priority,
})
}
return matches
}

func getServiceMatchPairs(service v1beta2.Service, ipv4Enabled, ipv6Enabled, matchSrc bool) [][]matchPair {
var conjMatchesMatchPairs [][]matchPair
ovsBitRanges := serviceToBitRanges(service)
addL4MatchPairs := func(matchKey *types.MatchKey) {
for _, ovsBitRange := range ovsBitRanges {
matches = append(matches,
&conjunctiveMatch{
tableID: ruleTableID,
matchKey: matchKey,
matchValue: ovsBitRange,
priority: priority,
})
conjMatchesMatchPairs = append(conjMatchesMatchPairs, []matchPair{{matchKey: matchKey, matchValue: ovsBitRange}})
}
}
return matches
switch *service.Protocol {
case v1beta2.ProtocolTCP:
if !matchSrc {
if ipv4Enabled {
addL4MatchPairs(MatchTCPDstPort)
}
if ipv6Enabled {
addL4MatchPairs(MatchTCPv6DstPort)
}
} else {
if ipv4Enabled {
addL4MatchPairs(MatchTCPSrcPort)
}
if ipv6Enabled {
addL4MatchPairs(MatchTCPv6SrcPort)
}
}
case v1beta2.ProtocolUDP:
if !matchSrc {
if ipv4Enabled {
addL4MatchPairs(MatchUDPDstPort)
}
if ipv6Enabled {
addL4MatchPairs(MatchUDPv6DstPort)
}
} else {
if ipv4Enabled {
addL4MatchPairs(MatchUDPSrcPort)
}
if ipv6Enabled {
addL4MatchPairs(MatchUDPv6SrcPort)
}
}
case v1beta2.ProtocolSCTP:
if ipv4Enabled {
addL4MatchPairs(MatchSCTPDstPort)
}
if ipv6Enabled {
addL4MatchPairs(MatchSCTPv6DstPort)
}
case v1beta2.ProtocolICMP:
if ipv4Enabled {
var matchPairs []matchPair
if service.ICMPType != nil {
matchPairs = append(matchPairs, matchPair{matchKey: MatchICMPType, matchValue: service.ICMPType})
}
if service.ICMPCode != nil {
matchPairs = append(matchPairs, matchPair{matchKey: MatchICMPCode, matchValue: service.ICMPCode})
}
if len(matchPairs) == 0 {
matchPairs = append(matchPairs, matchPair{matchKey: MatchICMPType, matchValue: nil})
}
conjMatchesMatchPairs = append(conjMatchesMatchPairs, matchPairs)
}
if ipv6Enabled {
var matchPairs []matchPair
if service.ICMPType != nil {
matchPairs = append(matchPairs, matchPair{matchKey: MatchICMPv6Type, matchValue: service.ICMPType})
}
if service.ICMPCode != nil {
matchPairs = append(matchPairs, matchPair{matchKey: MatchICMPv6Code, matchValue: service.ICMPCode})
}
if len(matchPairs) == 0 {
matchPairs = append(matchPairs, matchPair{matchKey: MatchICMPv6Type, matchValue: nil})
}
conjMatchesMatchPairs = append(conjMatchesMatchPairs, matchPairs)
}
default:
addL4MatchPairs(MatchTCPDstPort)
}
return conjMatchesMatchPairs
}

// serviceToBitRanges converts a Service to a list of BitRange.
Expand Down Expand Up @@ -782,7 +878,7 @@ func (c *clause) addAddrFlows(client *client, addrType types.AddressType, addres
func (c *clause) addServiceFlows(client *client, ports []v1beta2.Service, priority *uint16, matchSrc bool) []*conjMatchFlowContextChange {
var conjMatchFlowContextChanges []*conjMatchFlowContextChange
for _, port := range ports {
matches := generateServicePortConjMatches(c.ruleTable.GetID(), port, priority, client.networkConfig.IPv4Enabled, client.networkConfig.IPv6Enabled, matchSrc)
matches := generateServiceConjMatches(c.ruleTable.GetID(), port, priority, client.networkConfig.IPv4Enabled, client.networkConfig.IPv6Enabled, matchSrc)
for _, match := range matches {
ctxChange := c.addConjunctiveMatchFlow(client, match)
conjMatchFlowContextChanges = append(conjMatchFlowContextChanges, ctxChange)
Expand Down Expand Up @@ -995,7 +1091,7 @@ func (c *client) addRuleToConjunctiveMatch(conj *policyRuleConjunction, rule *ty
}
if conj.serviceClause != nil {
for _, port := range rule.Service {
matches := generateServicePortConjMatches(conj.serviceClause.ruleTable.GetID(), port, rule.Priority, c.networkConfig.IPv4Enabled, c.networkConfig.IPv6Enabled, false)
matches := generateServiceConjMatches(conj.serviceClause.ruleTable.GetID(), port, rule.Priority, c.networkConfig.IPv4Enabled, c.networkConfig.IPv6Enabled, false)
for _, match := range matches {
c.addActionToConjunctiveMatch(conj.serviceClause, match)
}
Expand Down Expand Up @@ -1025,7 +1121,7 @@ func (c *client) addActionToConjunctiveMatch(clause *clause, match *conjunctiveM
}
// Generate the default drop flow if dropTable is not nil.
if clause.dropTable != nil {
context.dropFlow = context.client.defaultDropFlow(clause.dropTable, match.matchKey, match.matchValue)
context.dropFlow = context.client.defaultDropFlow(clause.dropTable, match.matchPairs)
}
c.globalConjMatchFlowCache[matcherKey] = context
}
Expand Down Expand Up @@ -1068,7 +1164,7 @@ func (c *client) BatchInstallPolicyRuleFlows(ofPolicyRules []*types.PolicyRule)
for _, action := range ctx.actions {
actions = append(actions, action)
}
ctx.flow = c.conjunctiveMatchFlow(ctx.tableID, ctx.matchKey, ctx.matchValue, ctx.priority, actions)
ctx.flow = c.conjunctiveMatchFlow(ctx.tableID, ctx.matchPairs, ctx.priority, actions)
allFlows = append(allFlows, ctx.flow)
}
if ctx.dropFlow != nil {
Expand Down
37 changes: 30 additions & 7 deletions pkg/agent/openflow/pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -1993,6 +1993,26 @@ func (c *client) addFlowMatch(fb binding.FlowBuilder, matchKey *types.MatchKey,
if portValue.Value > 0 {
fb = fb.MatchSrcPort(portValue.Value, portValue.Mask)
}
case MatchICMPType:
fb = fb.MatchProtocol(matchKey.GetOFProtocol())
if matchValue != nil {
fb = fb.MatchICMPType(uint8(*matchValue.(*int32)))
}
case MatchICMPCode:
fb = fb.MatchProtocol(matchKey.GetOFProtocol())
if matchValue != nil {
fb = fb.MatchICMPCode(uint8(*matchValue.(*int32)))
}
case MatchICMPv6Type:
fb = fb.MatchProtocol(matchKey.GetOFProtocol())
if matchValue != nil {
fb = fb.MatchICMPv6Type(uint8(*matchValue.(*int32)))
}
case MatchICMPv6Code:
fb = fb.MatchProtocol(matchKey.GetOFProtocol())
if matchValue != nil {
fb = fb.MatchICMPv6Code(uint8(*matchValue.(*int32)))
}
case MatchServiceGroupID:
fb = fb.MatchRegFieldWithValue(ServiceGroupIDField, matchValue.(uint32))
}
Expand All @@ -2015,15 +2035,17 @@ func (c *client) conjunctionExceptionFlow(conjunctionID uint32, tableID uint8, n
}

// conjunctiveMatchFlow generates the flow to set conjunctive actions if the match condition is matched.
func (c *client) conjunctiveMatchFlow(tableID uint8, matchKey *types.MatchKey, matchValue interface{}, priority *uint16, actions []*conjunctiveAction) binding.Flow {
func (c *client) conjunctiveMatchFlow(tableID uint8, matchPairs []matchPair, priority *uint16, actions []*conjunctiveAction) binding.Flow {
var ofPriority uint16
if priority != nil {
ofPriority = *priority
} else {
ofPriority = priorityNormal
}
fb := getTableByID(tableID).BuildFlow(ofPriority)
fb = c.addFlowMatch(fb, matchKey, matchValue)
for _, eachMatchPair := range matchPairs {
fb = c.addFlowMatch(fb, eachMatchPair.matchKey, eachMatchPair.matchValue)
}
if c.deterministic {
sort.Sort(conjunctiveActionsInOrder(actions))
}
Expand All @@ -2034,19 +2056,20 @@ func (c *client) conjunctiveMatchFlow(tableID uint8, matchKey *types.MatchKey, m
}

// defaultDropFlow generates the flow to drop packets if the match condition is matched.
func (c *client) defaultDropFlow(table binding.Table, matchKey *types.MatchKey, matchValue interface{}) binding.Flow {
func (c *client) defaultDropFlow(table binding.Table, matchPairs []matchPair) binding.Flow {
fb := table.BuildFlow(priorityNormal)
for _, eachMatchPair := range matchPairs {
fb = c.addFlowMatch(fb, eachMatchPair.matchKey, eachMatchPair.matchValue)
}
if c.enableDenyTracking {
return c.addFlowMatch(fb, matchKey, matchValue).
Action().Drop().
return fb.Action().Drop().
Action().LoadRegMark(DispositionDropRegMark).
Action().LoadRegMark(CustomReasonDenyRegMark).
Action().SendToController(uint8(PacketInReasonNP)).
Cookie(c.cookieAllocator.Request(cookie.Default).Raw()).
Done()
}
return c.addFlowMatch(fb, matchKey, matchValue).
Action().Drop().
return fb.Action().Drop().
Cookie(c.cookieAllocator.Request(cookie.Default).Raw()).
Done()
}
Expand Down
1 change: 1 addition & 0 deletions pkg/agent/types/networkpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const (
IPNetAddr
OFPortAddr
L4PortAddr
ICMPAddr
ServiceGroupIDAddr
UnSupported
)
Expand Down
Loading