From bb195b1b523ae1e4949fcd201d6a0bf2c20fdb10 Mon Sep 17 00:00:00 2001 From: rachelc Date: Wed, 19 Oct 2022 11:08:28 +0300 Subject: [PATCH] add third parameter domainID/srcID to key in template cache for IPFix/v9 --- ipfix/decoder.go | 16 ++++++++-------- ipfix/decoder_test.go | 14 -------------- ipfix/memcache.go | 29 +++++------------------------ ipfix/memcache_test.go | 38 +++++++++++++++++++++++--------------- 4 files changed, 36 insertions(+), 61 deletions(-) diff --git a/ipfix/decoder.go b/ipfix/decoder.go index 600ff251..d7eb65c5 100644 --- a/ipfix/decoder.go +++ b/ipfix/decoder.go @@ -169,6 +169,7 @@ func (d *Decoder) decodeSet(mem MemCache, msg *Message) error { case rpcChan <- RPCRequest{ ID: setHeader.SetID, IP: d.raddr, + SrcID: msg.Header.DomainID, }: default: } @@ -199,14 +200,13 @@ func (d *Decoder) decodeSet(mem MemCache, msg *Message) error { if err == nil { mem.insert(tr.TemplateID, d.raddr, tr, msg.Header.DomainID) } - } else if setID <= 255 { - if setID == 0 { - // Invalid set - err = nonfatalError{fmt.Errorf("failed to decodeSet / invalid setID")} - } - // Reserved set, do not read any records - break - } else { + } else if setID >= 4 && setID <= 255 { + // Reserved set, do not read any records + break + } else if setID == 0 { + // Invalid set + return fmt.Errorf("failed to decodeSet / invalid setID") + } else { // Data set var data []DecodedField if data, err = d.decodeData(tr); err == nil { diff --git a/ipfix/decoder_test.go b/ipfix/decoder_test.go index e061b015..1682538d 100644 --- a/ipfix/decoder_test.go +++ b/ipfix/decoder_test.go @@ -230,17 +230,3 @@ func TestDecodeDataTpl(t *testing.T) { t.Error(err) } } - -func TestDecodeTemplateWithInvalidSetID(t *testing.T) { - var tpl = []byte{0, 10, 1, 32, 92, 88, 61, 152, 0, 1, 117, 22, 0, 0, 0, 0, /*invalid setID*/ 0, 0, 0, 68, 4, 0, 0, 15, 0, 153, 0, 8, 0, 152, 0, 8, 0, 1, 0, 8, 0, 2, 0, 8, 0, 60, 0, 1, 0, 10, 0, 4, 0, 14, 0, 4, 0, 61, 0, 1, 0, 8, 0, 4, 0, 12, 0, 4, 0, 7, 0, 2, 0, 11, 0, 2, 0, 5, 0, 1, 0, 6, 0, 1, 0, 4, 0, 1, 0, 2, 0, 68, 4, 1, 0, 15, 0, 153, 0, 8, 0, 152, 0, 8, 0, 1, 0, 8, 0, 2, 0, 8, 0, 60, 0, 1, 0, 10, 0, 4, 0, 14, 0, 4, 0, 61, 0, 1, 0, 8, 0, 4, 0, 12, 0, 4, 0, 7, 0, 2, 0, 11, 0, 2, 0, 5, 0, 1, 0, 6, 0, 1, 0, 4, 0, 1, 0, 2, 0, 68, 8, 0, 0, 15, 0, 153, 0, 8, 0, 152, 0, 8, 0, 1, 0, 8, 0, 2, 0, 8, 0, 60, 0, 1, 0, 10, 0, 4, 0, 14, 0, 4, 0, 61, 0, 1, 0, 27, 0, 16, 0, 28, 0, 16, 0, 5, 0, 1, 0, 7, 0, 2, 0, 11, 0, 2, 0, 6, 0, 1, 0, 4, 0, 1, 0, 2, 0, 68, 8, 1, 0, 15, 0, 153, 0, 8, 0, 152, 0, 8, 0, 1, 0, 8, 0, 2, 0, 8, 0, 60, 0, 1, 0, 10, 0, 4, 0, 14, 0, 4, 0, 61, 0, 1, 0, 27, 0, 16, 0, 28, 0, 16, 0, 5, 0, 1, 0, 7, 0, 2, 0, 11, 0, 2, 0, 6, 0, 1, 0, 4, 0, 1} - - ip := net.ParseIP("127.0.0.1") - mCache := GetCache("cache.file") - d := NewDecoder(ip, tpl) - _, err := d.Decode(mCache) - - expectedErrorStr := `failed to decodeSet / invalid setID` - if err != nil && err.Error() != expectedErrorStr { - t.Error("unexpected error happened:", err) - } -} diff --git a/ipfix/memcache.go b/ipfix/memcache.go index 561bad81..85ed053d 100644 --- a/ipfix/memcache.go +++ b/ipfix/memcache.go @@ -82,12 +82,12 @@ func GetCache(cacheFile string) MemCache { func (m MemCache) getShard(templateId uint16, addr net.IP, domainId uint32) (*TemplatesShard, uint32) { var key []byte hash := fnv.New32() - sId := make([]byte, 4) + dId := make([]byte, 4) tID := make([]byte, 2) - binary.LittleEndian.PutUint32(sId, domainId) + binary.LittleEndian.PutUint32(dId, domainId) binary.BigEndian.PutUint16(tID, templateId) key = append(key, addr...) - key = append(key, sId...) + key = append(key, dId...) key = append(key, tID...) hash.Write(key) @@ -96,14 +96,14 @@ func (m MemCache) getShard(templateId uint16, addr net.IP, domainId uint32) (*Te return m[uint(hSum32)%uint(shardNo)], hSum32 } -func (m *MemCache) insert(id uint16, addr net.IP, tr TemplateRecord, domainID uint32) { +func (m MemCache) insert(id uint16, addr net.IP, tr TemplateRecord, domainID uint32) { shard, key := m.getShard(id, addr, domainID) shard.Lock() defer shard.Unlock() shard.Templates[key] = Data{tr, time.Now().Unix()} } -func (m *MemCache) retrieve(id uint16, addr net.IP, domainID uint32) (TemplateRecord, bool) { +func (m MemCache) retrieve(id uint16, addr net.IP, domainID uint32) (TemplateRecord, bool) { shard, key := m.getShard(id, addr, domainID) shard.RLock() defer shard.RUnlock() @@ -130,25 +130,6 @@ func (m MemCache) allSetIds() []int { return result } -// Fill a slice with all known set ids and their field counts. This is inefficient and is only used for error reporting or debugging. -func (m MemCache) allSetIdsAndFieldCounts() []int { - num := 0 - for _, shard := range m { - num += len(shard.Templates) - } - result := make([]int, 0, num) - for _, shard := range m { - shard.RLock() - for _, set := range shard.Templates { - result = append(result, int(set.Template.TemplateID)) - result = append(result, int(set.Template.FieldCount)) - } - shard.RUnlock() - } - sort.Ints(result) - return result -} - // Dump saves the current templates to hard disk func (m MemCache) Dump(cacheFile string) error { b, err := json.Marshal( diff --git a/ipfix/memcache_test.go b/ipfix/memcache_test.go index 29ae035a..abc1b46b 100644 --- a/ipfix/memcache_test.go +++ b/ipfix/memcache_test.go @@ -79,24 +79,32 @@ func TestMemCacheAllSetIds(t *testing.T) { } func TestMemCache_keyWithDifferentDomainIDs(t *testing.T) { - var tpl1 TemplateRecord - var tpl2 TemplateRecord - + var tpl TemplateRecord ip := net.ParseIP("127.0.0.1") mCache := GetCache("cache.file") - tpl1.TemplateID = 310 - tpl1.FieldCount = 19 + tpl.TemplateID = 310 + tpl.FieldCount = 19 + mCache.insert(tpl.TemplateID, ip, tpl, 513) - tpl2.TemplateID = 310 - tpl2.FieldCount = 21 + tpl.FieldCount = 21 + mCache.insert(tpl.TemplateID, ip, tpl, 514) - mCache.insert(tpl1.TemplateID, ip, tpl1, 513) - mCache.insert(tpl2.TemplateID, ip, tpl2, 514) + v, ok := mCache.retrieve(tpl.TemplateID, ip, 513) - expected := []int{19, 21, 310, 310} - actual := mCache.allSetIdsAndFieldCounts() - if !reflect.DeepEqual(expected, actual) { - t.Errorf("Expected set IDs %v, got %v", expected, actual) - } -} + if !ok { + t.Error("expected mCache retrieve status true, got", ok) + } + if v.FieldCount != 19 { + t.Error("expected template id#:310 with Field count#:19, got", v.TemplateID, v.FieldCount) + } + + v, ok = mCache.retrieve(tpl.TemplateID, ip, 514) + + if !ok { + t.Error("expected mCache retrieve status true, got", ok) + } + if v.FieldCount != 21 { + t.Error("expected template id#:310 with Field count#:21, got", v.TemplateID, v.FieldCount) + } +} \ No newline at end of file