-
Notifications
You must be signed in to change notification settings - Fork 260
refactor: [NPM] General translation logic for egress and ingress #1106
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
Conversation
huntergregory
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious, should some srclist become dstlist for egress?
I should have noticed this last PR, but can we consolidate some structs/fields? Right now, we have the NPMNetworkPolicy.PodSelectorList, which is idential to information in NPMNetworkPolicy.PodSelectorIPSets with an additional included bool for each set. We also have labelSelector struct in parseSelector.go which is identical and copied over to the two structures above. We can consolidate these three duplicate structures/fields into a into a new struct in the policy package to prevent duplication and reduce the amount of code (less complex and less bug-prone):
Proposal
Remove the labelSelector struct and NPMNetworkPolicy.PodSelectorList field, and make the type of NPMNetworkPolicy.PodSelectorIPSets as IncludedTranslatedIPSet
type IncludedTranslatedIPSet struct {
Included bool
ipsets *[]TranslatedIPSet
}
To limit scope of this PR, we can leave the old NPMNetworkPolicy fields and add this as a new field. That way, current DP is unaffected, and we can follow up with a PR in DP.
| acl := policies.NewACLPolicy(npmNetPol.NameSpace, npmNetPol.Name, policies.Allowed, direction) | ||
| ruleIPSets, setInfo := allowAllInternal(matchType) | ||
| npmNetPol.RuleIPSets = append(npmNetPol.RuleIPSets, ruleIPSets) | ||
| acl.SrcList = append(acl.SrcList, setInfo) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be dstlist for egress?
| nsSelectorIPSets, nsSrcList := nameSpaceSelector(policies.SrcMatch, &flattenNSSelctor[i]) | ||
| npmNetPol.RuleIPSets = append(npmNetPol.RuleIPSets, nsSelectorIPSets...) | ||
| peerAndPortRule(npmNetPol, rule.Ports, nsSrcList) | ||
| // #2. From fields exist in rule |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: from or to field exists
| // to handle multiple values in matchExpressions spec. | ||
| flattenNSSelctor := flattenNameSpaceSelector(peer.NamespaceSelector) | ||
| for i := range flattenNSSelctor { | ||
| nsSelectorIPSets, nsSrcList := nameSpaceSelector(matchType, &flattenNSSelctor[i]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: flattenNSSelector
| for i, rule := range ingress { | ||
| translateRule(npmNetPol, policies.Ingress, policies.SrcMatch, i, rule.Ports, rule.From) | ||
| } | ||
| // Except for allow all traffic case in #1, the rest of them should not have default drop rules. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: should this say "should have default drop rule"? (same with comment in ingress == nil check)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same for egress function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Good catch!
| } | ||
|
|
||
| // #2. If ingress is nil (in yaml file, it is specified with '[]'), it means "Deny all" - it does not allow receiving any traffic from others. | ||
| if ingress == nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we could remove this check since the for loop will do nothing if ingress is nil
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
similar for egress function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. Initially, I did it and functionally there is no different, but to better understanding code and maintenance of code, I explicitly put two exceptional cases (e.g., allAllow and allDeny).
In this translation package, there are some codes which can be reduced, but just make different functions as well for better understanding (e.g., parsePodSelector or parseNSSelector, etc).
I am fine to either way (current one or merging one).
Please let me know if you think merging (only for loop) is better.
I can revise and put comment about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For understanding and maintenance, makes sense to keep. Having an extra if-check shouldn't hurt performance anyways
| const ( | ||
| SrcMatch MatchType = 0 | ||
| DstMatch MatchType = 1 | ||
| SrcMatch MatchType = 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to change this type to string for easier debugging from print statements. I could do that in my PR or you could
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am fine if you have ideas to better code, but do we have matchTypeStrings map just below this code?
- https://github.com/Azure/azure-container-networking/blob/master/npm/pkg/dataplane/policies/policy.go#L191
Always glad if you can make better one. If so, please make different PR for them. I think it used in several place and easy to have one simple PR.
@huntergregory There is one question about DstDstMatch (https://github.com/Azure/azure-container-networking/blob/master/npm/pkg/dataplane/policies/policy.go#L188)
// TODO(jungukcho) Question - Why it is 3, not 2?
DstDstMatch MatchType = 3There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had all the combinations before (SrcSrcMatch was 2), so it's leftover from that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, since there's a map already, this should be a separate PR change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If so, I will revise it to below code.
// Possible MatchTypes.
const (
SrcMatch MatchType = 0
DstMatch MatchType = 1
// MatchTypes with 2 locations (e.g. DstDst) are for ip and port respectively.
DstDstMatch MatchType = 2
// This is used for podSelector under spec. It can be Src or Dst based on existence of ingress or egress rule.
EitherMatch MatchType = 3
)| // (e.g., IPBlock, podSelector, namespaceSelector, or both podSelector and namespaceSelector) | ||
| func peerAndPortRule(npmNetPol *policies.NPMNetworkPolicy, ports []networkingv1.NetworkPolicyPort, setInfo []policies.SetInfo) { | ||
| // (e.g., IPBlock, podSelector, namespaceSelector, or both podSelector and namespaceSelector). | ||
| func peerAndPortRule(npmNetPol *policies.NPMNetworkPolicy, direction policies.Direction, ports []networkingv1.NetworkPolicyPort, setInfo []policies.SetInfo) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this affect the acl dstlist for egress? if so should modify the variable names used as args to calls to this func to be something like srcOrDstList
You confirmed ports are always for the destination for either ingress/egress, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch.
I will walk through dstlist and srclist.
Yes. Confirmed that ports are always for destination.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Revised them now with a method.
However, it seems we can do better job with only one PeerList instead of having two SrcList and DstList.
I put the comment about it, but want to do it next PR even though it makes sense since it needs to change in multiple places. wdyt?
I will walk through
Yes. Good suggestion.
|
If we change later, we can get to integration testing quicker, but then we might notice bugs and have to make fixes based on structs that we won't use later. I don't have a strong opinion. |
Anyway if we change some codes, we need to do integration test again even though it is non-functional change (and we don't waste time your point - but then we might notice bugs and have to make fixes based on structs that we won't use later.). So, let's complete some necessary code change and PRs first and then plan integration test. We don't need to rush. |
I walked through the code (including linux dataplane) to see how it uses data structures and think I prefer to having two members (i.e., PodSelectorIPSets and PodSelectorList) since two data structures have different data when there is azure-container-networking/npm/pkg/controlplane/translation/translatePolicy_test.go Line 618 in 306b665
So, I am fine to a current code, but if you have another opinion, please let me know. |
huntergregory
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. We have some cleanup work to do later in Translation & Dataplane:
- switching to
PeerListinstead ofSrcListandDstListlike you suggested - deciding what to do for pod selector structs
| ports []networkingv1.NetworkPolicyPort, peers []networkingv1.NetworkPolicyPeer) { | ||
| // TODO(jungukcho): need to clean up it. | ||
| // Leave allowExternal variable now while the condition is checked before calling this function. | ||
| allowExternal, portRuleExists, fromRuleExists := ruleExists(ports, peers) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: fromRuleExists to peerRuleExists
Thank you for summary. Will add them in a note in this PR as well and revisit them in a next PR. |
Reason for Change:
This PR is to support egress and generalizes translation for egress and ingress.
Issue Fixed:
Requirements:
Notes:
As @huntergregory summarized, next PR will deal with below lists.
PeerListinstead ofSrcListandDstListlike you suggested