-
Notifications
You must be signed in to change notification settings - Fork 373
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
Implement openflow metrics query interface #1140
Conversation
Thanks for your PR. The following commands are available:
|
28f25c2
to
2ae1b29
Compare
2ae1b29
to
6e82cf0
Compare
6e82cf0
to
cb0be5d
Compare
/test-all |
cb0be5d
to
84f1af1
Compare
Codecov Report
@@ Coverage Diff @@
## master #1140 +/- ##
==========================================
+ Coverage 56.20% 56.29% +0.08%
==========================================
Files 105 108 +3
Lines 11550 12027 +477
==========================================
+ Hits 6492 6770 +278
- Misses 4490 4669 +179
- Partials 568 588 +20
Flags with carried forward coverage won't be shown. Click here to find out more.
|
84f1af1
to
7432a45
Compare
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.
Could you update the title of the PR and commit to something more specific? "Implement policy metrics" is too high level and may be confusing since this is only a part of "policy metrics", maybe "Implement openflow metrics query interface"
@weiqiangt @tnqn Apologies. I didn't realize that this PR was part of #1172. I left some relevant comments in that other PR. |
7432a45
to
415714c
Compare
Thanks for reviewing, I have updated the code according to your comment. |
415714c
to
29371e8
Compare
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.
Thanks for the change. I have a couple of comments.
pkg/agent/openflow/network_policy.go
Outdated
m := types.RuleMetric{} | ||
pkts, _ := strconv.ParseUint(segs[1][strings.Index(segs[1], "=")+1:], 10, 32) | ||
m.Packets = pkts | ||
if strings.Contains(segs[4], "+") { |
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.
Example format to cover this scenario would be good I guess.
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.
Thanks, added the example format.
pkg/agent/openflow/network_policy.go
Outdated
} | ||
|
||
func parseMetricFlow(flow string) (uint32, types.RuleMetric) { | ||
if strings.Contains(flow, "reg0") { |
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: drop identifier would make this easy to read?
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.
Thanks, added.
pkg/ovs/openflow/ofctrl_builder.go
Outdated
@@ -184,6 +184,33 @@ func (b *ofFlowBuilder) MatchCTMarkMask(mask uint32) FlowBuilder { | |||
return b | |||
} | |||
|
|||
func (b *ofFlowBuilder) MatchCTLabel(high, low uint64) FlowBuilder { |
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.
Is this used somewhere?
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.
Nope, removed.
pkg/ovs/openflow/ofctrl_builder.go
Outdated
b.ofFlow.Match.CtLabelHiMask <<= rng[0] - 64 | ||
b.ofFlow.Match.CtLabelHiMask <<= 127 - rng[1] | ||
b.ofFlow.Match.CtLabelHiMask <<= 127 - rng[1] | ||
b.ofFlow.Match.CtLabelHiMask = 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.
Is this supposed to be CtLabelHiMask as the range doesn't involve LabelLo value?
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.
Thanks for pointing it out. I have updated this part and extract the bit operations to a separate function with a unit test covers.
29371e8
to
f0f3844
Compare
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.
some minor follow-up comments
pkg/agent/openflow/network_policy.go
Outdated
|
||
func (c *client) NetworkPolicyMetrics() map[uint32]*types.RuleMetric { | ||
result := map[uint32]*types.RuleMetric{} | ||
egressFlows, _ := c.ovsctlClient.DumpTableFlows(uint8(EgressMetricTable)) |
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 commented in #1172 (comment). I wasn't suggesting making it a field in the client, just having a local variable for 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.
Done.
pkg/agent/openflow/network_policy.go
Outdated
for _, flows := range [][]string{egressFlows, ingressFlows} { | ||
for _, flow := range flows { | ||
if strings.Contains(flow, "priority=0") { | ||
continue | ||
} | ||
ruleID, metric := parseMetricFlow(flow) | ||
// We have two flows for each allow rule. One with ct_state=+new matching calculates session numbers, | ||
// and first packets, another ct_state=-new flow is used to calculate following packets. We need to merge | ||
// metrics of these two flows to get the right number. | ||
if accMetric, ok := result[ruleID]; ok { | ||
accMetric.Merge(metric) | ||
} else { | ||
result[ruleID] = &metric | ||
} | ||
} | ||
} |
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 actually thought you were going to have something like this:
collectMetricsFromFlows := func(flows []string) {
for _, flow := range flows {
// ...
}
}
collectMetricsFromFlows(egressFlows)
collectMetricsFromFlows(ingressFlows)
(not a big fan of the [][]string
and double for loop)
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.
Sure, updated.
f0f3844
to
a75185d
Compare
/test-all |
pkg/agent/openflow/network_policy.go
Outdated
pkts, _ := strconv.ParseUint(segs[1][strings.Index(segs[1], "=")+1:], 10, 32) | ||
m.Packets = pkts | ||
m.Sessions = pkts | ||
bytes, _ := strconv.ParseUint(segs[2][strings.Index(segs[2], "=")+1:], 10, 32) |
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.
It will overflow once it exceeds 4G bytes? I think all the 3 metrics should be 64 bit size.
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.
Thanks for pointing it out, updated.
pkg/agent/openflow/pipeline.go
Outdated
EgressReg regType = 5 | ||
IngressReg regType = 6 | ||
TraceflowReg regType = 9 // Use reg9[28..31] to store traceflow dataplaneTag. | ||
cnpDropConjunctionIDReg = endpointIPReg // marksRegServiceNeedLB indicates a packet need to do service selection. |
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.
comment doesn't match, and I think using number directly is more straightforward, people may be confused by endpointIPReg
, I thought they have some association before, but they just share the reg, 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.
Sure, updated.
pkg/agent/openflow/pipeline.go
Outdated
if !ingress { | ||
metricTableID = EgressMetricTable | ||
offset = 32 | ||
labelRange = binding.Range{32, 63} |
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.
declaring labelRange as two global variables to avoid repeated allocation, for example low32Range, high32Range?
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.
Updated.
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.
Updated.
pkg/agent/openflow/pipeline.go
Outdated
conjReg = EgressReg | ||
labelRange = binding.Range{32, 63} |
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.
ditto
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.
Updated.
pkg/agent/types/networkpolicy.go
Outdated
Bytes, Packets, Sessions uint64 | ||
} | ||
|
||
func (m *RuleMetric) Merge(m1 RuleMetric) { |
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.
Use pointer to avoid struct copy?
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.
Sure, updated.
9211e3c
to
7f55ced
Compare
pkg/agent/openflow/pipeline.go
Outdated
// cnpDropConjunctionIDReg reuses reg3 which will also be used for storing endpoint IP to store the rule ID. Since | ||
// the service selection will finish when a packet hitting NetworkPolicy related rules, there is no conflict. | ||
cnpDropConjunctionIDReg regType = 3 | ||
marksRegServiceNeedLB uint32 = 0b001 // marksRegServiceNeedLB indicates a packet need to do service selection. |
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: why changing the comment position? I think the previous one is more common and neat
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.
Reverted.
- Add flows to calculate packet and session numbers of each NetworkPolicy rule. - Provide functions to query metrics of each NetworkPolicy rule. Signed-off-by: Weiqiang Tang <weiqiangt@vmware.com>
7f55ced
to
3ea1d22
Compare
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.
thanks @weiqiangt, LGTM
/test-all |
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 understand that this is merged. Trying to use this patch for adding netpol info in flow records. Have a couple of questions.
What happens to ct_label if both cluster network policy rule and k8s rule are applied on to one flow? Do we support this scenario?
bytes, _ := strconv.ParseUint(segs[2][strings.Index(segs[2], "=")+1:], 10, 64) | ||
m.Bytes = bytes | ||
idRaw := segs[5][strings.Index(segs[5], "0x")+2 : strings.Index(segs[5], "/")] | ||
if len(idRaw) > 8 { // only 32 bits are valid. |
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.
What happens to egress rule if only 32 bits are valid? I see that in ct_label we use 64 bits like below:
// We use the 0..31 bits of the ct_label to store the ingress rule ID and use the 32..63 bits to store the
// egress rule ID.
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.
Thanks for pointing it out, this should be a bug. I will create a PR to fix 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.
When matching egress rule, there should always be 8 trailing zero while the length of the matching pattern of ingress rule will never exceed 8.
In other words, if the length of idRaw
exceeds 8, it must for egress, otherwise it's for ingress.
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 see.. makes sense. The comment was a bit confusing and misleading.
For now, only the ID of the last rule which takes effect will be calculated. |
Okay. Maybe using the rest of 64bits is probably the right way I guess, right? |
Please ignore the above comment. I confirmed with @abhiraut that only one rule either from cluster network policy or K8s network policy is being applied. |
- Add flows to calculate packet and session numbers of each NetworkPolicy rule. - Provide functions to query metrics of each NetworkPolicy rule. Signed-off-by: Weiqiang Tang <weiqiangt@vmware.com>
rule.