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

Implement bulk updates to IP sets #1357

Merged
merged 5 commits into from Mar 1, 2017
Merged

Conversation

fasaxc
Copy link
Member

@fasaxc fasaxc commented Feb 20, 2017

  • Improve IP sets update performance by batching multiple set updates into single ipset restore calls.
  • Avoid buffering large amounts of input/output by doing streaming reads/writes from pipes to the child process.
  • Replace AttemptCleanup() start-of-day cleanup routine with a resync mechanism that reads back the contents of the dataplane. Works around / Fixes #1347.

Design:

  • Move write function to Registry, renamed as IPSets.
  • Reduce IPSet struct to a data struct rather than a fully fledged object to avoid having an intricate coupling between the two objects.
  • To support comparison during resync, convert IPs/CIDRs to canonical form and store them as ip.Addr/ip.CIDR objects instead.
  • Remove IP set existence cache since logic is now rolled into resync.

TODO:

  • Reinstate UTs.

@fasaxc
Copy link
Member Author

fasaxc commented Feb 21, 2017

retest this please

Copy link
Member

@nelljerram nelljerram left a comment

Choose a reason for hiding this comment

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

Comments inline. In addition, I wondered about renaming the remaining 'ipsetReg' variables.

members set.Set

// pendingReplace is either nil to indicate that there is no pending replace or a set
// containing all the entries that we want to write.
Copy link
Member

Choose a reason for hiding this comment

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

Can you extend this comment to provide similar info for pendingAdds and pendingDeletions?

pendingDeletions set.Set
}

// IPVersionConfig wraps up the metadata for a particular IP version. It can be used by other
Copy link
Member

Choose a reason for hiding this comment

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

Delete "other" at end of previous line.

versionedPrefixes = append(versionedPrefixes, prefix+version)
}
versionedPrefixes = append(versionedPrefixes, extraUnversionedIPSets...)
ourNamesPattern := "^(" + strings.Join(versionedPrefixes, "|") + ")"
Copy link
Member

Choose a reason for hiding this comment

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

Should really regexp-quote each element of versionedPrefixes, here.

// NameForMainIPSet converts the given IP set ID (example: "qMt7iLlGDhvLnCjM0l9nzxbabcd"), to
// a name for use in the dataplane. The return value will have the configured prefix and is
// guaranteed to be short enough to use as an ipset name (example:
// "cali6ts:qMt7iLlGDhvLnCjM0l9nzxb").
Copy link
Member

Choose a reason for hiding this comment

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

cali6-s:qMt7iLlGDhvLnCjM0l9nzxb

ipsets/ipsets.go Outdated
"github.com/projectcalico/felix/set"
)

// IPSets manages a whole "plane" of IP sets, i.e. all the IPv4 or IPv6 IP sets.
Copy link
Member

Choose a reason for hiding this comment

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

I'm being picky, but someone could still misunderstand that. I think it could be made idiot-proof as "all the IPv4 IP sets, or all the IPv6 IP sets."

ipsets/ipsets.go Outdated
line := scanner.Text()
if line == "" {
// End of members
ipSetName = ""
Copy link
Member

Choose a reason for hiding this comment

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

Don't reset ipSetName here; instead do it at the close of the for loop, so as also to catch the EOF case.

ipsets/ipsets.go Outdated
return nil
}
logCxt.Info("Calculating deltas to IP set")
return s.writeDeltas(ipSet, w)
Copy link
Member

Choose a reason for hiding this comment

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

Pass down (and use) the logCxt here?

ipsets/ipsets.go Outdated
// - membersInDataplane nil
// - pendingAdds/Deletions empty.
logCxt.Info("Doing full IP set rewrite")
return s.writeFullRewrite(ipSet, w)
Copy link
Member

Choose a reason for hiding this comment

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

(similarly here)

ipsets/ipsets.go Outdated
}

// ApplyDeletions tries to delete any IP sets that are no longer needed.
// Failures are ignored, deletions will be retried the next time AttemptCleanup() is called.
Copy link
Member

Choose a reason for hiding this comment

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

s/AttemptCleanup/ApplyDeletions/

ipsets/ipsets.go Outdated
return set.RemoveItem
})

s.gaugeNumIpsets.Set(float64(len(s.ipSetIDToIPSet)))
Copy link
Member

Choose a reason for hiding this comment

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

Presumably s.ipSetIDToIPSet should be decremented in this code path, but I don't see where that is happening.

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 was just using this as a point in the code where we know we've got no updates in flight. Added a comment.

- Move ipset restore logic to IPSets "manager" class so multiple
  writes can be grouped together.
- Do writes in a streaming fashion to minimise need for buffering in
  memory.
- Canonicalise IP set members when adding to IPset in preparation
  for impelmenting resync.
- Load IP sets from datatplane and convert members to canonical form.
- Compare with expected values and queue up updates to repair.
@fasaxc fasaxc force-pushed the ipsets-perf branch 2 times, most recently from 148b510 to 9a780a5 Compare February 28, 2017 16:24
@fasaxc
Copy link
Member Author

fasaxc commented Feb 28, 2017

@neiljerram Think I've addressed all your comments now. Back to you for re-review.

@fasaxc fasaxc removed their assignment Feb 28, 2017
@nelljerram
Copy link
Member

retest this please

1 similar comment
@fasaxc
Copy link
Member Author

fasaxc commented Mar 1, 2017

retest this please

@fasaxc fasaxc merged commit bcef187 into projectcalico:master Mar 1, 2017
@fasaxc fasaxc deleted the ipsets-perf branch March 1, 2017 13:09
song-jiang pushed a commit to song-jiang/felix that referenced this pull request Aug 30, 2017
Implement bulk updates to IP sets

-  Improve IP sets update performance by batching multiple set updates into single ipset restore calls.  
- Avoid buffering large amounts of input/output by doing streaming reads/writes from pipes to the child process.
- Replace `AttemptCleanup()` start-of-day cleanup routine with a resync mechanism that reads back the contents of the dataplane.  Works around / Fixes #1347. 

Design:

- Move write function to `Registry`, renamed as `IPSets`.
- Reduce IPSet struct to a data struct rather than a fully fledged object to avoid having an intricate coupling between the two objects.
- To support comparison during resync, convert IPs/CIDRs to canonical form and store them as ip.Addr/ip.CIDR objects instead.
- Remove IP set existence cache since logic is now rolled into resync.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants