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

Support sending IPFIX flow records for Antrea flow exporter #825

Merged
merged 15 commits into from
Aug 11, 2020

Conversation

srikartati
Copy link
Member

@srikartati srikartati commented Jun 11, 2020

Added support to export IPFIX flow records that are built from
connection map using IPFIX library.

Tested with local IPFIX collector running in k8s cluster. Unit tests were added. Test with
elastiflow collector in progress.

Fixes# 712

@antrea-bot
Copy link
Collaborator

Thanks for your PR.
Unit tests and code linters are run automatically every time the PR is updated.
E2e, conformance and network policy tests can only be triggered by a member of the vmware-tanzu organization. Regular contributors to the project should join the org.

The following commands are available:

  • /test-e2e: to trigger e2e tests.
  • /skip-e2e: to skip e2e tests.
  • /test-conformance: to trigger conformance tests.
  • /skip-conformance: to skip conformance tests.
  • /test-networkpolicy: to trigger networkpolicy tests.
  • /skip-networkpolicy: to skip networkpolicy tests.
  • /test-windows-conformance: to trigger windows conformance tests.
  • /skip-windows-conformance: to skip windows conformance tests.
  • /test-all: to trigger all tests.
  • /skip-all: to skip all tests.

These commands can only be run by members of the vmware-tanzu organization.

@srikartati srikartati changed the title Support sending IPFIX flow records as part of flow exporter feature Support sending IPFIX flow records for Antrea flow exporter feature Jun 11, 2020
@srikartati srikartati changed the title Support sending IPFIX flow records for Antrea flow exporter feature [WIP]Support sending IPFIX flow records for Antrea flow exporter feature Jun 11, 2020
@srikartati srikartati force-pushed the ipfix_record branch 2 times, most recently from 51f7ec1 to ac163fd Compare June 15, 2020 07:10
@srikartati
Copy link
Member Author

I did testing with IPFIX collector (C-based ipfixlib) in a local k8s cluster running iperf service with 2 tcp clients and one server. Collector is able to see all the data records sent at ipfix export interval. Posting output for reference below. In the process, fixed some bugs in previous patch and ipfix library.
Could not generate mocks for ipfix based interfaces without the IPFIX library in github.com. I will add mentioned unit tests in exporter_test.go, when the library is available in vmware github org.

IPFIX-HDR:
 version=10, length=185
 unixtime=1592204240 (2020-06-14 23:57:20 PDT)
 seqno=2, odid=1269807227
DATA RECORD: 
 template id:  256 
 nfields:      19
 flowStartSeconds: 18446744011573954816
 flowEndSeconds: 18446744011573954816
 sourceIPv4Address: 100.10.1.62
 destinationIPv4Address: 100.10.1.64
 sourceTransportPort: 47614
 destinationTransportPort: 8080
 protocolIdentifier: 6
 packetTotalCount: 1613320
 octetTotalCount: 76543694782
 packetDeltaCount: 1613320
 octetDeltaCount: 76543694782
 reverse packetTotalCount: 89493
 reverse octetTotalCount: 4654376
 reverse packetDeltaCount: 89493
 reverse octetDeltaCount: 4654376
 55829_101: 0x7765622d636c69656e742d353463663739376637642d6462776d70
 55829_100: 0x64656661756c74
 55829_103: 0x7765622d7365727665722d353836366436636434352d6a63747a34
 55829_102: 0x64656661756c74

@srikartati srikartati force-pushed the ipfix_record branch 4 times, most recently from 1c86e77 to 09a1c32 Compare June 16, 2020 19:53
@srikartati srikartati changed the title [WIP]Support sending IPFIX flow records for Antrea flow exporter feature Support sending IPFIX flow records for Antrea flow exporter feature Jun 16, 2020
@srikartati
Copy link
Member Author

Added few unit test. Using the go-ipfixlib at "github.com/srikartati/go-ipfixlib" by making it public.

@srikartati srikartati changed the title Support sending IPFIX flow records for Antrea flow exporter feature Support sending IPFIX flow records for Antrea flow exporter Jun 17, 2020
Copy link
Contributor

@jianjuns jianjuns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A general question - have we observed higher CPU usage/contention when flow exporting is enabled?

cmd/antrea-agent/agent.go Outdated Show resolved Hide resolved
pkg/agent/flowexporter/exporter/exporter.go Show resolved Hide resolved
pkg/agent/flowexporter/connections/connections.go Outdated Show resolved Hide resolved
defer cs.mutex.Unlock()

for k, v := range cs.connections {
cs.mutex.Unlock()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not safe to iterate a map without lock? What happens if another routine add/delete keys?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is possible when conntrack poller go routine accessing the map. Doing this to avoid lock contention on whole map, when we are building flow record for a single connection. The disadvantage is that we may send connection data of last poll cycle (difference in seconds) for very few flow records--as this is continuous monitoring, I thought this is ok. What is your opinion?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to provide some further clarification, by considering a scenario, w.r.t following code. Here as well if routine executing iterate grabs the lock first, then we will build records using old connection data. However, by releasing lock after every item, we can decrease the contention.

lock
addOrUpdateConnectionMap
unlock

lock
IterateConnectionMap
unlock

Also, I would like to note that range connectionMap will iterate on old copy of connection map even connection map is updated in other routine. I missed that in my previous comment. Thanks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not know map iteration in Golang is thread safe.
Anyway could you add some comments to explain why you release the lock there, and what could be the impact?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, Jianjun. Iteration over the map is not thread-safe depending on concurrent operations. Releasing lock in our case may work because of current deletion logic, and the presumption that sending old connection data is fine. Added the comment in the code. Please take a look.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds tricky. Have you verified it really works?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It worked as expected with respect to deletion logic. However, because of the IPFIX collector requirement of sending accurate flow records rather than from the last poll cycle, I changed the synchronization logic.

@@ -36,3 +41,11 @@ type Connection struct {
DestinationPodNamespace string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add some comments somewhere indicating Pod name/NS is filled only when the Pod is local?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A general question - have we observed higher CPU usage/contention when flow exporting is enabled?

I did not look closely into CPU utilization stats yet. I will compare the following scenarios w.r.t cpu utilization and percentage of used and runnable times for processes:

  • No flow exporter
  • Flow exporter with no workload
  • Flow exporter with workload.

pkg/agent/flowexporter/exporter/exporter.go Outdated Show resolved Hide resolved
Copy link
Member Author

@srikartati srikartati left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will checkin the fixes along with the e2e test in the next patch. Please let me know if you have further comments. Thanks.

defer cs.mutex.Unlock()

for k, v := range cs.connections {
cs.mutex.Unlock()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is possible when conntrack poller go routine accessing the map. Doing this to avoid lock contention on whole map, when we are building flow record for a single connection. The disadvantage is that we may send connection data of last poll cycle (difference in seconds) for very few flow records--as this is continuous monitoring, I thought this is ok. What is your opinion?

pkg/agent/flowexporter/connections/connections.go Outdated Show resolved Hide resolved
pkg/agent/flowexporter/connections/connections.go Outdated Show resolved Hide resolved
pkg/agent/flowexporter/exporter/exporter.go Outdated Show resolved Hide resolved
@antrea-bot
Copy link
Collaborator

Thanks for your PR.
Unit tests and code linters are run automatically every time the PR is updated.
E2e, conformance and network policy tests can only be triggered by a member of the vmware-tanzu organization. Regular contributors to the project should join the org.

The following commands are available:

  • /test-e2e: to trigger e2e tests.
  • /skip-e2e: to skip e2e tests.
  • /test-conformance: to trigger conformance tests.
  • /skip-conformance: to skip conformance tests.
  • /test-whole-conformance: to trigger all conformance tests on linux.
  • /skip-whole-conformance: to skip all conformance tests on linux.
  • /test-networkpolicy: to trigger networkpolicy tests.
  • /skip-networkpolicy: to skip networkpolicy tests.
  • /test-windows-conformance: to trigger windows conformance tests.
  • /skip-windows-conformance: to skip windows conformance tests.
  • /test-all: to trigger all tests (except whole conformance).
  • /skip-all: to skip all tests (except whole conformance).

These commands can only be run by members of the vmware-tanzu organization.

Changed synchronization logic for poll(ConnectionStore.Run) and
export(FlowExporter.Run) go routines.
Fixed e2e tests.
First record should send 0 delta bytes/packets otherwise already
established flow will show incorrect throughput (Mb/s or PPS)
This will be removed when network policy info is added in flow records.
@antrea-bot
Copy link
Collaborator

Thanks for your PR.
Unit tests and code linters are run automatically every time the PR is updated.
E2e, conformance and network policy tests can only be triggered by a member of the vmware-tanzu organization. Regular contributors to the project should join the org.

The following commands are available:

  • /test-e2e: to trigger e2e tests.
  • /skip-e2e: to skip e2e tests.
  • /test-conformance: to trigger conformance tests.
  • /skip-conformance: to skip conformance tests.
  • /test-whole-conformance: to trigger all conformance tests on linux.
  • /skip-whole-conformance: to skip all conformance tests on linux.
  • /test-networkpolicy: to trigger networkpolicy tests.
  • /skip-networkpolicy: to skip networkpolicy tests.
  • /test-windows-conformance: to trigger windows conformance tests.
  • /skip-windows-conformance: to skip windows conformance tests.
  • /test-windows-networkpolicy: to trigger windows networkpolicy tests.
  • /skip-windows-networkpolicy: to skip windows networkpolicy tests.
  • /test-hw-offload: to trigger ovs hardware offload test.
  • /skip-hw-offload: to skip ovs hardware offload test.
  • /test-all: to trigger all tests (except whole conformance).
  • /skip-all: to skip all tests (except whole conformance).

Major change is handling of error in exporter go routine.

func (exp *ipfixExportingProcess) CloseConnToCollector() {
exp.ExportingProcess.CloseConnToCollector()
return
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return not needed (same below and maybe in other places?)

}

// CheckAndDoExport enables us to export flow records periodically at a given flow export frequency.
func (exp *flowExporter) CheckAndDoExport(collector net.Addr, pollDone chan struct{}) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the Check part of the name is a bit misleading and not needed. I would suggest removing it altogether. Or at least mention in the comment that the function ensures there is a live connection to the collector.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed the name.

klog.V(2).Infof("Successfully exported IPFIX flow records")
}

return
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return not needed

flowExporter := exporter.NewFlowExporter(
flowrecords.NewFlowRecords(connStore),
o.config.FlowExportFrequency)
go wait.Until(func() { flowExporter.CheckAndDoExport(o.flowCollector, pollDone) }, o.pollInterval, stopCh)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's not exactly what I had in mind here. You should still have a select loop in CheckAndDoExport, the time duration provided here should be one second or a few seconds, and should only be used to establish the connection again in case of error.

in case of error, CheckAndDoExport logs the error, then returns. wait.Until will then take care of calling it again (which will establish the connection, and start a new for / select loop). If the connection never breaks or there is no export error, CheckAndDoExport will not return.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I handled the connection creation through if exp.process == nil only when there is error.
I have to change this when we move the handling of connection logic to go-ipfix. Keeping this as is for now as discussed offline.

for _, flow := range outputFlow {
conn, err := flowStringToAntreaConnection(flow, zoneFilter)
if err != nil {
klog.Warningf("Ignoring the flow from conntrack dump due to the error: %v", err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
klog.Warningf("Ignoring the flow from conntrack dump due to the error: %v", err)
klog.Warningf("Ignoring the flow from conntrack dump due parsing error: %v", err)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@srikartati
Copy link
Member Author

/test-all

@srikartati
Copy link
Member Author

/test-networkpolicy
/test-e2e
/test-conformance

@srikartati srikartati force-pushed the ipfix_record branch 2 times, most recently from f1744e4 to b8d9ee4 Compare August 11, 2020 02:18
@srikartati
Copy link
Member Author

/test-all

for {
select {
case <-stopCh:
break
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/break/return


rc, collectorOutput, _, err := provider.RunCommandOnNode(masterNodeName(), fmt.Sprintf("kubectl logs ipfix-collector -n antrea-test"))
if err != nil || rc != 0 {
t.Fatalf("error when getting logs %v, rc: %v", err, rc)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: first letter of log message should be capitalized

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

t.Fatalf("Error in converting octetDeltaCount to int type")
}
// compute the bandwidth using 5s as interval
recBandwidth := (deltaBytes * 8.0) / float64((int64(5.0))*time.Second.Nanoseconds())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

recBandwidth := (deltaBytes * 8.0) / float64(5*time.Second.Nanoseconds())

does not work?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it works. For some reason, I started with 5.0 to make everything float and navigated around that. Changed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missed this change. As tests have finished in this PR, modified this file in this PR #984 .

@srikartati
Copy link
Member Author

/test-all

Copy link
Contributor

@antoninbas antoninbas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

A few things we talked about offline to keep in mind for post 0.9:

  • handle reconnections to the IPFix collector in the go-ipfix library
  • add unit tests for the reconnection case if possible
  • improve OVS appctl connection parsing logic

@srikartati
Copy link
Member Author

LGTM.

A few things we talked about offline to keep in mind for post 0.9:

  • handle reconnections to the IPFix collector in the go-ipfix library
  • add unit tests for the reconnection case if possible
  • improve OVS appctl connection parsing logic

Thanks for the review. Yes there is an issue for the first one in go-ipfix. I will keep a note of the last one to enhance OVS appctl dump flows function. This is needed for windows support.

@srikartati srikartati merged commit c9d365d into antrea-io:master Aug 11, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants