Skip to content

Commit

Permalink
Merge pull request #295 from gunjan5/random-hashing
Browse files Browse the repository at this point in the history
hostname based hashing
  • Loading branch information
gunjan5 authored Dec 8, 2016
2 parents d0cb244 + dac571a commit e44106f
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 7 deletions.
2 changes: 1 addition & 1 deletion lib/client/ipam.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ func (c ipams) autoAssign(num int, handleID *string, attrs map[string]string, po
// or the request has been satisfied.
for _, p := range pools {
log.Debugf("Assigning from random blocks in pool %s", p.String())
newBlock := randomBlockGenerator(p)
newBlock := randomBlockGenerator(p, host)
for rem > 0 {
// Grab a new random block.
blockCIDR := newBlock()
Expand Down
14 changes: 9 additions & 5 deletions lib/client/ipam_block_reader_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ package client
import (
goerrors "errors"
"fmt"
"hash/fnv"
"math/big"
"math/rand"
"net"
"reflect"
"time"

log "github.com/Sirupsen/logrus"
"github.com/projectcalico/libcalico-go/lib/api"
Expand Down Expand Up @@ -118,7 +118,7 @@ func (rw blockReaderWriter) claimNewAffineBlock(
for _, pool := range pools {
// Use a block generator to iterate through all of the blocks
// that fall within the pool.
blocks := randomBlockGenerator(pool)
blocks := randomBlockGenerator(pool, host)
for subnet := blocks(); subnet != nil; subnet = blocks() {
// Check if a block already exists for this subnet.
log.Debugf("Getting block: %s", subnet.String())
Expand Down Expand Up @@ -327,7 +327,7 @@ func blockGenerator(pool cnet.IPNet) func() *cnet.IPNet {
// Returns a generator that, when called, returns a random
// block from the given pool. When there are no blocks left,
// the it returns nil.
func randomBlockGenerator(pool cnet.IPNet) func() *cnet.IPNet {
func randomBlockGenerator(pool cnet.IPNet, hostName string) func() *cnet.IPNet {

// Determine the IP type to use.
version := getIPVersion(cnet.IP{pool.IP})
Expand All @@ -340,8 +340,12 @@ func randomBlockGenerator(pool cnet.IPNet) func() *cnet.IPNet {
numBlocks := new(big.Int)
numBlocks.Div(numIP, big.NewInt(blockSize))

// Start at a random offset index
source := rand.NewSource(time.Now().UnixNano())
// Create a random number generator seed based on the hostname.
// This is to avoid assigning multiple blocks when multiple
// workloads request IPs around the same time.
hostHash := fnv.New32()
hostHash.Write([]byte(hostName))
source := rand.NewSource(int64(hostHash.Sum32()))
randm := rand.New(source)

// initialIndex keeps track of the random starting point
Expand Down
3 changes: 2 additions & 1 deletion lib/client/randomblock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,14 @@ func poolTest(cidr string) {
}
var pools []cnet.IPNet
pools = []cnet.IPNet{{*subnet}}
host := "testHost"

for _, pool := range pools {

ones, size := pool.Mask.Size()
prefixLen := size - ones
numIP := new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(prefixLen)), nil)
blocks := randomBlockGenerator(pool)
blocks := randomBlockGenerator(pool, host)

blockCount := big.NewInt(0)
for blk := blocks(); blk != nil; blk = blocks() {
Expand Down

0 comments on commit e44106f

Please sign in to comment.