diff --git a/agents/agentreq.go b/agents/agentreq.go index 3831008c0..d859e2732 100644 --- a/agents/agentreq.go +++ b/agents/agentreq.go @@ -169,7 +169,7 @@ func (aReq *AgentRequest) ParseField( case utils.META_CONSTANT: out, err = cfgFld.Value.ParseValue(utils.EmptyString) isString = true - case utils.META_COMPOSED: + case utils.MetaVariable, utils.META_COMPOSED: out, err = cfgFld.Value.ParseDataProvider(aReq, utils.NestingSep) isString = true case utils.META_USAGE_DIFFERENCE: diff --git a/agents/diam_it_test.go b/agents/diam_it_test.go index c1ac278e7..aded2d18c 100644 --- a/agents/diam_it_test.go +++ b/agents/diam_it_test.go @@ -190,6 +190,34 @@ func testDiamItDryRun(t *testing.T) { }, }), }}) + ccr.NewAVP(avp.MultipleServicesCreditControl, avp.Mbit, 0, &diam.GroupedAVP{ // Multiple-Services-Credit-Control + AVP: []*diam.AVP{ + diam.NewAVP(avp.UsedServiceUnit, avp.Mbit, 0, &diam.GroupedAVP{ // Used-Service-Unit + AVP: []*diam.AVP{ + diam.NewAVP(avp.CCTotalOctets, avp.Mbit, 0, datatype.Unsigned64(7640)), // CC-Total-Octets + diam.NewAVP(avp.CCInputOctets, avp.Mbit, 0, datatype.Unsigned64(5337)), // CC-Input-Octets + diam.NewAVP(avp.CCOutputOctets, avp.Mbit, 0, datatype.Unsigned64(2303)), // CC-Output-Octets + }, + }), + diam.NewAVP(avp.ServiceIdentifier, avp.Mbit, 0, datatype.Unsigned32(65000)), // Service-Identifier + diam.NewAVP(avp.RatingGroup, avp.Mbit, 0, datatype.Unsigned32(1)), // Rating-Group + diam.NewAVP(avp.ReportingReason, avp.Mbit, 0, datatype.Enumerated(2)), // Reporting-Reason + }, + }) + ccr.NewAVP(avp.MultipleServicesCreditControl, avp.Mbit, 0, &diam.GroupedAVP{ // Multiple-Services-Credit-Control + AVP: []*diam.AVP{ + diam.NewAVP(avp.UsedServiceUnit, avp.Mbit, 0, &diam.GroupedAVP{ // Used-Service-Unit + AVP: []*diam.AVP{ + diam.NewAVP(avp.CCTotalOctets, avp.Mbit, 0, datatype.Unsigned64(3000)), // CC-Total-Octets + diam.NewAVP(avp.CCInputOctets, avp.Mbit, 0, datatype.Unsigned64(2000)), // CC-Input-Octets + diam.NewAVP(avp.CCOutputOctets, avp.Mbit, 0, datatype.Unsigned64(1000)), // CC-Output-Octets + }, + }), + diam.NewAVP(avp.ServiceIdentifier, avp.Mbit, 0, datatype.Unsigned32(65000)), // Service-Identifier + diam.NewAVP(avp.RatingGroup, avp.Mbit, 0, datatype.Unsigned32(2)), // Rating-Group + diam.NewAVP(avp.ReportingReason, avp.Mbit, 0, datatype.Enumerated(2)), // Reporting-Reason + }, + }) if _, err := ccr.NewAVP("Framed-IP-Address", avp.Mbit, 0, datatype.UTF8String("10.228.16.4")); err != nil { t.Error(err) } @@ -279,13 +307,29 @@ func testDiamItDryRun(t *testing.T) { } else { if val, err := diamAVPAsString(avps[0]); err != nil { t.Error(err) - } else if val != "65000" { - t.Errorf("expecting: 65000, received: <%s>", val) + } else if val != "1" { + t.Errorf("expecting: 1, received: <%s>", val) } if val, err := diamAVPAsString(avps[1]); err != nil { t.Error(err) - } else if val != "100" { - t.Errorf("expecting: 100, received: <%s>", val) + } else if val != "2" { + t.Errorf("expecting: 2, received: <%s>", val) + } + } + if avps, err := msg.FindAVPsWithPath([]interface{}{"Multiple-Services-Credit-Control", "Used-Service-Unit", "CC-Total-Octets"}, dict.UndefinedVendorID); err != nil { + t.Error(err) + } else if len(avps) != 2 { + t.Errorf("Unexpected number of Multiple-Services-Credit-Control.Used-Service-Unit.CC-Total-Octets : %d", len(avps)) + } else { + if val, err := diamAVPAsString(avps[0]); err != nil { + t.Error(err) + } else if val != "7640" { + t.Errorf("expecting: 7640, received: <%s>", val) + } + if val, err := diamAVPAsString(avps[1]); err != nil { + t.Error(err) + } else if val != "3000" { + t.Errorf("expecting: 3000, received: <%s>", val) } } eVal = "6" // sum of items diff --git a/agents/libdiam.go b/agents/libdiam.go index d2e9e5879..546363597 100644 --- a/agents/libdiam.go +++ b/agents/libdiam.go @@ -340,12 +340,19 @@ func (dP *diameterDP) FieldAsInterface(fldPath []string) (data interface{}, err if err != nil { return nil, err } - 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) + var fltrAVPs []*diam.AVP + for i := len(pathIface) - 1; i > 0; i-- { + pathIface[i] = slctr.AttrName() // search for AVPs which are having common path but different end element + pathIface = pathIface[:i+1] + if fltrAVPs, err = dP.m.FindAVPsWithPath(pathIface, dict.UndefinedVendorID); err != nil || len(fltrAVPs) != 0 { + break // found AVPs or got error, go and compare + } + } if err != nil { return nil, err } else if len(fltrAVPs) == 0 || len(fltrAVPs) != len(avps) { - return nil, utils.ErrFilterNotPassingNoCaps + return nil, fmt.Errorf("%s for selector %s", + utils.ErrFilterNotPassingNoCaps.Error(), slctr.AttrName()) } for k, fAVP := range fltrAVPs { if dataAVP, err := diamAVPAsIface(fAVP); err != nil { diff --git a/data/conf/samples/diamagent/dryrun.json b/data/conf/samples/diamagent/dryrun.json index 1cbc8d995..32a756e2c 100644 --- a/data/conf/samples/diamagent/dryrun.json +++ b/data/conf/samples/diamagent/dryrun.json @@ -16,18 +16,29 @@ "value":"~*req.Inexistent", "manadatory":false}, {"tag": "OriginID", "field_id": "OriginID", "type": "*composed", "value": "~*req.Session-Id", "mandatory": true}, - {"tag": "RequestType", "field_id": "RequestType", "type": "*constant", "value": "*prepaid"}, - {"tag": "SetupTime", "field_id": "SetupTime", "type": "*composed", "value": "~*req.Event-Timestamp", "mandatory": true}, + {"tag": "RequestType", "field_id": "RequestType", + "type": "*constant", "value": "*prepaid"}, + {"tag": "SetupTime", "field_id": "SetupTime", "type": "*composed", + "value": "~*req.Event-Timestamp", "mandatory": true}, + {"tag": "UsedUnits1", "field_id": "UsedUnits1", "type": "*composed", "mandatory": true, + "value": "~*req.Multiple-Services-Credit-Control.Used-Service-Unit.CC-Total-Octets[~Rating-Group(1)]"}, + {"tag": "UsedUnits2", "field_id": "UsedUnits2", "type": "*composed", "mandatory": true, + "value": "~*req.Multiple-Services-Credit-Control.Used-Service-Unit.CC-Total-Octets[~Rating-Group(2)]"}, + ], "reply_fields":[ {"tag": "CCATemplate", "type": "*template", "value": "*cca"}, {"tag": "ResultCode", "field_id": "Result-Code", "type": "*constant", "value": "2002"}, {"tag": "RatingGroup", "field_id": "Multiple-Services-Credit-Control.Rating-Group", - "type": "*constant", "value": "65000","new_branch": true}, + "type": "*constant", "value": "1"}, + {"tag": "CCTotalOctets1", "field_id": "Multiple-Services-Credit-Control.Used-Service-Unit.CC-Total-Octets", + "type": "*variable", "value": "~*cgreq.UsedUnits1"}, {"tag": "RatingGroup", "field_id": "Multiple-Services-Credit-Control.Rating-Group", - "type": "*constant", "value": "100","new_branch": true}, + "type": "*constant", "value": "2","new_branch": true}, + {"tag": "CCTotalOctets2", "field_id": "Multiple-Services-Credit-Control.Used-Service-Unit.CC-Total-Octets", + "type": "*variable", "value": "~*cgreq.UsedUnits2"}, {"tag": "GrantedUsage", "field_id": "Granted-Service-Unit.CC-Time", "type": "*sum", - "value": "~*cgreq.Val1;~*cgreq.Val2;~*cgreq.Val3"}, + "value": "~*cgreq.Val1;~*cgreq.Val2;~*cgreq.Val3"}, ], }, ], diff --git a/utils/consts.go b/utils/consts.go index e5402619a..39638d662 100755 --- a/utils/consts.go +++ b/utils/consts.go @@ -311,6 +311,7 @@ const ( HIERARCHY_SEP = ">" META_COMPOSED = "*composed" META_USAGE_DIFFERENCE = "*usage_difference" + MetaVariable = "*variable" MetaCCUsage = "*cc_usage" MetaString = "*string" NegativePrefix = "!"