From 23a27afaa2966c0e7be0e5416271c167232a9fbf Mon Sep 17 00:00:00 2001 From: DanB Date: Mon, 24 Sep 2018 13:14:26 +0200 Subject: [PATCH] Multiple filter selectors in diameter group AVP rules --- agents/libdmt.go | 57 ++++++++++++++++++++++++++----------------- agents/libdmt_test.go | 15 ++++++++++++ 2 files changed, 50 insertions(+), 22 deletions(-) diff --git a/agents/libdmt.go b/agents/libdmt.go index d21e0f263..1bfd9baeb 100644 --- a/agents/libdmt.go +++ b/agents/libdmt.go @@ -176,30 +176,43 @@ func (dP *diameterDP) FieldAsInterface(fldPath []string) (data interface{}, err slectedIdx := 0 // by default we select AVP[0] if slctrStr != "" { if slectedIdx, err = strconv.Atoi(slctrStr); err != nil { // not int, compile it as RSRParser - var slctr config.RSRParsers - if slctr, err = config.NewRSRParsersFromSlice(strings.Split(slctrStr, "|"), true); err != nil { - return nil, err - } else if len(slctr) == 0 { - return nil, fmt.Errorf("unsupported filter selector: <%s>", slctrStr) - } - pathIface[len(pathIface)-1] = slctr[0].AttrName() // search for AVPs which are having common path but different end element - fltrAVPs, err := dP.m.FindAVPsWithPath(pathIface, dict.UndefinedVendorID) - if err != nil { - return nil, err - } else if len(fltrAVPs) == 0 || len(fltrAVPs) != len(avps) { - return nil, utils.ErrFilterNotPassingNoCaps - } - for k, fAVP := range fltrAVPs { - if dataAVP, err := diamAVPAsIface(fAVP); err != nil { + selIndxs := make(map[int][]struct{}) // use it to find intersection of all matched filters + slctrStrs := strings.Split(slctrStr, "|") + for _, slctrStr := range slctrStrs { + slctr, err := config.NewRSRParser(slctrStr, true) + if err != nil { return nil, err - } else if _, err := slctr.ParseValue(dataAVP); err != nil { // filter not passing - if err != utils.ErrFilterNotPassingNoCaps { - return nil, err - } - continue // filter not passing, not really error - } else { - slectedIdx = k // filter passing, found our match, select the index of AVP to return } + pathIface[len(pathIface)-1] = slctr.AttrName() // search for AVPs which are having common path but different end element + fltrAVPs, err := dP.m.FindAVPsWithPath(pathIface, dict.UndefinedVendorID) + if err != nil { + return nil, err + } else if len(fltrAVPs) == 0 || len(fltrAVPs) != len(avps) { + return nil, utils.ErrFilterNotPassingNoCaps + } + for k, fAVP := range fltrAVPs { + if dataAVP, err := diamAVPAsIface(fAVP); err != nil { + return nil, err + } else if _, err := slctr.ParseValue(dataAVP); err != nil { + if err != utils.ErrFilterNotPassingNoCaps { + return nil, err + } + continue // filter not passing, not really error + } else { + selIndxs[k] = append(selIndxs[k], struct{}{}) // filter passing, index it + } + } + } + var oneMatches bool + for idx, matches := range selIndxs { + if len(matches) == len(slctrStrs) { // all filters in selection matching + oneMatches = true + slectedIdx = idx + break + } + } + if !oneMatches { + return nil, utils.ErrFilterNotPassingNoCaps } } } diff --git a/agents/libdmt_test.go b/agents/libdmt_test.go index c76d30127..982b11c27 100644 --- a/agents/libdmt_test.go +++ b/agents/libdmt_test.go @@ -48,11 +48,19 @@ func TestDPFieldAsInterface(t *testing.T) { AVP: []*diam.AVP{ diam.NewAVP(450, avp.Mbit, 0, datatype.Enumerated(0)), // Subscription-Id-Type diam.NewAVP(444, avp.Mbit, 0, datatype.UTF8String("33708000003")), // Subscription-Id-Data + diam.NewAVP(avp.ValueDigits, avp.Mbit, 0, datatype.Integer64(10000)), }}) m.NewAVP("Subscription-Id", avp.Mbit, 0, &diam.GroupedAVP{ AVP: []*diam.AVP{ diam.NewAVP(450, avp.Mbit, 0, datatype.Enumerated(1)), // Subscription-Id-Type diam.NewAVP(444, avp.Mbit, 0, datatype.UTF8String("208708000003")), // Subscription-Id-Data + diam.NewAVP(avp.ValueDigits, avp.Mbit, 0, datatype.Integer64(20000)), + }}) + m.NewAVP("Subscription-Id", avp.Mbit, 0, &diam.GroupedAVP{ + AVP: []*diam.AVP{ + diam.NewAVP(450, avp.Mbit, 0, datatype.Enumerated(1)), // Subscription-Id-Type + diam.NewAVP(444, avp.Mbit, 0, datatype.UTF8String("208708000004")), // Subscription-Id-Data + diam.NewAVP(avp.ValueDigits, avp.Mbit, 0, datatype.Integer64(30000)), }}) dP := newDADataProvider(m) @@ -81,6 +89,13 @@ func TestDPFieldAsInterface(t *testing.T) { } else if eOut != out { t.Errorf("Expecting: %v, received: %v", eOut, out) } + eOut = interface{}("208708000004") + if out, err := dP.FieldAsInterface([]string{"Subscription-Id", + "Subscription-Id-Data[~Subscription-Id-Type(1)|~Value-Digits(30000)]"}); err != nil { // on multiple filter + t.Error(err) + } else if eOut != out { + t.Errorf("Expecting: %v, received: %v", eOut, out) + } eOut = interface{}("33708000003") if out, err := dP.FieldAsInterface([]string{"Subscription-Id", "Subscription-Id-Data"}); err != nil { t.Error(err)