Changes for Sy
authorEduardo Ramos Testillano <eduardo.ramos.testillano@ericsson.com>
Sun, 28 Feb 2016 20:25:37 +0000 (21:25 +0100)
committerEduardo Ramos Testillano <eduardo.ramos.testillano@ericsson.com>
Sun, 28 Feb 2016 20:25:37 +0000 (21:25 +0100)
1. Store Subscriber (MSISDN, IMSI) as testcase witness, and not only the Session-Id
2. In tinyTestcase.sh, in case of SLR waitfc programming, we need the subscriber condition, not the Session-Id, because that session is created in the client (PCRF) and can't know it.
   2.1 By the way, change tsharkDecoder.sh to get MSISDN and IMSI
   2.2 Answers must copy the Session-Id from the corresponding request in case of difference (SLR/A, for example; in case of RAR/A, no problem because is the Gx session created in
       ADML system too)

3. Allow test|<id>|sendxml2e/2c|step number  (specially 2c), to be used as step reference not only for answers build, but for further requests (SNR for example) which should transport
   the same Session-Id.

example/diameter/launcher/Launcher.cpp
example/diameter/launcher/resources/scripts/tinyTestcase.sh
example/diameter/launcher/testing/TestCase.cpp
example/diameter/launcher/testing/TestManager.cpp
example/diameter/launcher/testing/TestManager.hpp
example/diameter/launcher/testing/TestStep.cpp
example/diameter/pcapDecoder/tsharkDecoder.sh

index f58157f..563ee5b 100644 (file)
@@ -1202,6 +1202,8 @@ std::string Launcher::help() const throw() {
   result += "\n                                                          the difficulty of predicting these information). Be sure to";
   result += "\n                                                          refer to a 'wait for request' step. Conditions like 'regexp'";
   result += "\n                                                          (as we will see later) are not verified.";
+  result += "\n                                                         In the case of requests, the step number is used to force the";
+  result += "\n                                                          copy of Session-Id value from the referred step.";
   result += "\n";
   result += "\n                              sendxml2c|<source_file>[|<step number>]";
   result += "\n                                                         Sends xml source file (pathfile) to client (it would be a";
index 24046b1..22e2748 100755 (executable)
@@ -6,6 +6,7 @@
 SCR_DIR=`readlink -f $0 | xargs dirname`
 TESTCASE_BN=testcase.txt
 WHAT=?????????
+REQUEST_STEP=
 
 #############
 # FUNCTIONS #
@@ -108,9 +109,15 @@ update_testcase () {
   local s_wait="test|1|$wait_command|$code|$((1-isrequest))"
   [ -n "$sessionid" ] && s_wait="${s_wait}|||${sessionid}"
 
+  local s_send="test|1|$send_command|$xml"
+
   if [ $isrequest -eq 1 ]
   then
-    echo "test|1|$send_command|$xml" >> $TESTCASE_BN
+    # Send the request
+    # Special case for SNR/SNA (code=8388636): the Session-Id is created on client and received on SLR previously
+    [ "$code" = "8388636" -a "$adml_type" = "server" ] && s_send="test|1|$send_command|$xml|$REQUEST_STEP"
+    echo "$s_send" >> $TESTCASE_BN
+
     if [ -n "$resultcode" ]
     then
       local hbh="$(grep -o "hop-by-hop-id=\"[0-9]*\"" $xml)"
@@ -122,12 +129,21 @@ update_testcase () {
         _rc=$(getResultCode $ans_xml)
         [ -n "$_rc" ] && rc=$_rc
       fi
+
+      # Wait the answer:
       s_wait="${s_wait}|${rc}"
     fi
     echo "$s_wait" >> $TESTCASE_BN
   else
+    local next_step_number=$((lines+1))
+
+    # Wait the request
+    # Special case for SLR/SLA (code=8388635): the Session-Id is created on client
+    [ "$code" = "8388635" -a "$adml_type" = "server" ] && { s_wait="test|1|$wait_command|$code|1||||$subscriber" ; REQUEST_STEP=$next_step_number ; }
     echo "$s_wait" >> $TESTCASE_BN
-    echo "test|1|$send_command|$xml|$((lines+1))" >> $TESTCASE_BN
+
+    # Send the answer
+    echo "test|1|$send_command|$xml|$next_step_number" >> $TESTCASE_BN
   fi
 }
 
index 5678ff0..087e29b 100644 (file)
@@ -230,9 +230,11 @@ void TestCase::assertInitialized() const throw(anna::RuntimeException) {
 void TestCase::assertMessage(const anna::DataBlock &db, bool toEntity) throw(anna::RuntimeException) {
 
   bool isRequest = anna::diameter::codec::functions::isRequest(db);
-  bool registerSessionId = ((isRequest && toEntity) || (!isRequest && !toEntity) /* (*) */);
-  // (*) we register answers Session-Id assuming that we will know the Session-Id values created by the client (OCS)
-  // This is another solution for TODO(***) regarding diameter server testing. No sure about the final implementation.
+  bool registerKeys = ((isRequest && toEntity) || (!isRequest && !toEntity) /* (*) */);
+  // (*) we register answers Session-Id "assuming" that we will know the Session-Id values created by the client.
+  // This is another solution regarding diameter server testing. No sure about the final implementation.
+  // We will help registering also subscriber data, because certain messages (i.e. SLR) coming from clients could
+  //  have specific Session-Id value (unknown at test programming), and normally are identified by subscriber.
 
   // Check hop-by-hop:
   if (isRequest) {
@@ -242,8 +244,18 @@ void TestCase::assertMessage(const anna::DataBlock &db, bool toEntity) throw(ann
     a_hopByHops[hbh] = NULL; // may be assigned to a wait condition
   }
 
-  if (registerSessionId)
-    TestManager::instantiate().registerSessionId(anna::diameter::helpers::base::functions::getSessionId(db), this);
+  if (registerKeys) {
+    TestManager &testManager = TestManager::instantiate();
+    testManager.registerSessionId(anna::diameter::helpers::base::functions::getSessionId(db), this);
+
+
+    std::string subscriberId = anna::diameter::helpers::dcca::functions::getSubscriptionIdData(db, anna::diameter::helpers::dcca::AVPVALUES__Subscription_Id_Type::END_USER_E164);
+    if (subscriberId == "") // try with IMSI
+      subscriberId = anna::diameter::helpers::dcca::functions::getSubscriptionIdData(db, anna::diameter::helpers::dcca::AVPVALUES__Subscription_Id_Type::END_USER_IMSI);
+
+    if (subscriberId != "")
+      testManager.registerSubscriberId(subscriberId, this);
+  }
 }
 
 void TestCase::addTimeout(const anna::Millisecond &timeout) throw(anna::RuntimeException) {
index 75955ce..fbee74d 100644 (file)
@@ -16,6 +16,7 @@
 #include <anna/app/functions.hpp>
 #include <anna/timex/Engine.hpp>
 #include <anna/diameter/helpers/base/functions.hpp>
+#include <anna/diameter/helpers/dcca/functions.hpp>
 #include <anna/diameter.comm/ClientSession.hpp>
 #include <anna/diameter.comm/ServerSession.hpp>
 
@@ -114,6 +115,21 @@ void TestManager::registerSessionId(const std::string &sessionId, const TestCase
   }
 }
 
+void TestManager::registerSubscriberId(const std::string &subscriberId, const TestCase *testCase)  throw(anna::RuntimeException) {
+
+  std::map<std::string /* subscriber id's */, TestCase*>::const_iterator it = a_subscriberIdTestCaseMap.find(subscriberId);
+  if (it != a_subscriberIdTestCaseMap.end()) { // found
+    unsigned int id = it->second->getId();
+    if (id != testCase->getId()) {
+      throw anna::RuntimeException(anna::functions::asString("There is another test case (id = %llu) which registered such subscriberId: %s", id, subscriberId.c_str()), ANNA_FILE_LOCATION);
+    }
+  }
+  else {
+    a_subscriberIdTestCaseMap[subscriberId] = const_cast<TestCase*>(testCase);
+    LOGDEBUG(anna::Logger::debug(anna::functions::asString("TestManager::registerSubscriberId for test case (id = %llu): %s)", testCase->getId(), subscriberId.c_str()), ANNA_FILE_LOCATION));
+  }
+}
+
 TestTimer* TestManager::createTimer(TestCaseStep* testCaseStep, const anna::Millisecond &timeout, const TestTimer::Type::_v type)
 throw(anna::RuntimeException) {
   TestTimer* result(NULL);
@@ -266,6 +282,7 @@ bool TestManager::clearPool() throw() {
 
   a_testPool.clear();
   a_sessionIdTestCaseMap.clear();
+  a_subscriberIdTestCaseMap.clear();
   a_currentTestIt = a_testPool.end();
   a_poolCycle = 1;
   configureTTPS(0); // stop
@@ -282,6 +299,7 @@ bool TestManager::resetPool(bool hard) throw() {
       result = true;
   }
   //a_sessionIdTestCaseMap.clear();
+  //a_subscriberIdTestCaseMap.clear();
   return result;
 }
 
@@ -362,14 +380,33 @@ TestCase *TestManager::getTestCaseFromSessionId(const anna::DataBlock &message,
   }
   catch (anna::RuntimeException &ex) {
     //ex.trace();
-    LOGWARNING(anna::Logger::warning("Cannot get the Session-Id from received DataBlock in order to identify the Test Case", ANNA_FILE_LOCATION));
+    LOGDEBUG(anna::Logger::debug("Cannot get the Session-Id from received DataBlock in order to identify the Test Case", ANNA_FILE_LOCATION));
     return NULL;
   }
   std::map<std::string /* session id's */, TestCase*>::const_iterator sessionIdIt = a_sessionIdTestCaseMap.find(sessionId);
   if (sessionIdIt != a_sessionIdTestCaseMap.end())
     return sessionIdIt->second;
 
-  LOGWARNING(anna::Logger::warning(anna::functions::asString("Cannot identify the Test Case for received Session-Id: %s", sessionId.c_str()), ANNA_FILE_LOCATION));
+  LOGDEBUG(anna::Logger::debug(anna::functions::asString("Cannot identify the Test Case for received Session-Id: %s", sessionId.c_str()), ANNA_FILE_LOCATION));
+  return NULL;
+}
+
+TestCase *TestManager::getTestCaseFromSubscriberId(const anna::DataBlock &message, std::string &subscriberId) throw() {
+  try {
+    subscriberId = anna::diameter::helpers::dcca::functions::getSubscriptionIdData(message, anna::diameter::helpers::dcca::AVPVALUES__Subscription_Id_Type::END_USER_E164);
+    if (subscriberId == "") // try with IMSI
+      subscriberId = anna::diameter::helpers::dcca::functions::getSubscriptionIdData(message, anna::diameter::helpers::dcca::AVPVALUES__Subscription_Id_Type::END_USER_IMSI);
+  }
+  catch (anna::RuntimeException &ex) {
+    //ex.trace();
+    LOGDEBUG(anna::Logger::debug("Cannot get the Subscriber-Id from received DataBlock in order to identify the Test Case", ANNA_FILE_LOCATION));
+    return NULL;
+  }
+  std::map<std::string /* subscriber id's */, TestCase*>::const_iterator subscriberIdIt = a_subscriberIdTestCaseMap.find(subscriberId);
+  if (subscriberIdIt != a_subscriberIdTestCaseMap.end())
+    return subscriberIdIt->second;
+
+  LOGDEBUG(anna::Logger::debug(anna::functions::asString("Cannot identify the Test Case for received Subscriber-Id: %s", subscriberId.c_str()), ANNA_FILE_LOCATION));
   return NULL;
 }
 
@@ -379,9 +416,14 @@ void TestManager::receiveMessage(const anna::DataBlock &message, OriginHost *hos
   if (!tests()) return;
 
   // Identify the test case:
-  std::string sessionId;
-  TestCase *tc = getTestCaseFromSessionId(message, sessionId);
-  if (!tc) return;
+  std::string sessionId, subscriberId;
+  TestCase *tc;
+  tc = getTestCaseFromSessionId(message, sessionId);
+  if (!tc) getTestCaseFromSubscriberId(message, subscriberId);
+  if (!tc) {
+    LOGWARNING(anna::Logger::warning(anna::comm::functions::asText("Cannot identify the Test Case for the message received from server: ", message), ANNA_FILE_LOCATION)); // this should not appear
+    return;
+  }
 
   // Work with Test case:
   TestStepWait *tsw = tc->searchNextWaitConditionFulfilled(message, true /* comes from entity */);
@@ -419,9 +461,14 @@ void TestManager::receiveMessage(const anna::DataBlock &message, OriginHost *hos
   if (!tests()) return;
 
   // Identify the test case:
-  std::string sessionId;
-  TestCase *tc = getTestCaseFromSessionId(message, sessionId);
-  if (!tc) return;
+  std::string sessionId, subscriberId;
+  TestCase *tc;
+  tc = getTestCaseFromSessionId(message, sessionId);
+  if (!tc) getTestCaseFromSubscriberId(message, subscriberId);
+  if (!tc) {
+    LOGWARNING(anna::Logger::warning(anna::comm::functions::asText("Cannot identify the Test Case for the message received from client: ", message), ANNA_FILE_LOCATION)); // this should not appear
+    return;
+  }
 
   // Work with Test case:
   TestStepWait *tsw = tc->searchNextWaitConditionFulfilled(message, false /* comes from client */);
index 10ca097..d1cc1c1 100644 (file)
@@ -97,9 +97,14 @@ class TestManager : public anna::timex::TimeEventObserver, public anna::Singleto
   // Test timers
   timer_container a_timers;
 
+  // Test case identifiers:
   // Session-Id's
   std::map<std::string /* session id's */, TestCase*> a_sessionIdTestCaseMap; // stores used Session-Id values within a test case.
                                                                               // No other can use them, but a test case could use more than one.
+  // Subscriber's
+  std::map<std::string /* subscriber id's */, TestCase*> a_subscriberIdTestCaseMap; // stores used Subscriber-Id values within a test case.
+
+
 
   StatSummary a_statSummary; // general statistics
 
@@ -115,6 +120,7 @@ class TestManager : public anna::timex::TimeEventObserver, public anna::Singleto
   public:
 
     void registerSessionId(const std::string &sessionId, const TestCase *testCase) throw(anna::RuntimeException);
+    void registerSubscriberId(const std::string &subscriberId, const TestCase *testCase) throw(anna::RuntimeException);
 
     int tests() const throw() { return a_testPool.size(); }
     void setTimerController(anna::timex::Engine *engine) throw() {  a_timeController = engine; }
@@ -163,6 +169,7 @@ class TestManager : public anna::timex::TimeEventObserver, public anna::Singleto
 
     // Main logic
     TestCase *getTestCaseFromSessionId(const anna::DataBlock &message, std::string &sessionId) throw();
+    TestCase *getTestCaseFromSubscriberId(const anna::DataBlock &message, std::string &subscriberId) throw();
     void receiveMessage(const anna::DataBlock &message, OriginHost *host, const anna::diameter::comm::ClientSession *clientSession) throw(anna::RuntimeException);
     void receiveMessage(const anna::DataBlock &message, OriginHost *host, const anna::diameter::comm::ServerSession *serverSession) throw(anna::RuntimeException);
 
index 07ed685..fdbd798 100644 (file)
@@ -353,41 +353,49 @@ throw() {
 
 bool TestStepSendxml::do_execute() throw() {
   bool success = false;
-  std::string failReason, s_warn;
+  std::string failReason;
   MyDiameterEntity *entity = a_originHost->getEntity(); // by default
   MyLocalServer *localServer = a_originHost->getDiameterServer(); // by default
   const TestStepWait *tsw = NULL;
-
-  // Create comm message:
   anna::diameter::comm::Message *msg = a_originHost->createCommMessage();
-  //msg->clearBody();
-  msg->setBody(a_message);
 
   try {
-    // Update sequence for answers:
-    if (a_waitForRequestStepNumber != -1) { // is an answer: try to copy sequence information; alert about Session-Id discrepance
-      // Request which was received:
-      tsw = static_cast<const TestStepWait*>(a_testCase->getStep(a_waitForRequestStepNumber));
 
-      const anna::DataBlock &request = tsw->getMsgDataBlock();
-      anna::diameter::HopByHop hbh = anna::diameter::codec::functions::getHopByHop(request);
-      anna::diameter::EndToEnd ete = anna::diameter::codec::functions::getEndToEnd(request);
+    if (a_waitForRequestStepNumber != -1) {
 
-      // Update sequence:
-      anna::diameter::codec::functions::setHopByHop(a_message, hbh);
-      anna::diameter::codec::functions::setEndToEnd(a_message, ete);
+      // Referenced request in the 'wait for request step':
+      tsw = static_cast<const TestStepWait*>(a_testCase->getStep(a_waitForRequestStepNumber));
+      const anna::DataBlock &referenceRequest = tsw->getMsgDataBlock();
+      std::string sessionIdReferenceRequest = anna::diameter::helpers::base::functions::getSessionId(referenceRequest);
+      bool thisIsAnswer = anna::diameter::codec::functions::isRequest(getMsgDataBlock());
 
-      // Check Session-Id for warning ...
-      std::string sessionIdAnswer = anna::diameter::helpers::base::functions::getSessionId(a_message);
-      std::string sessionIdRequest = anna::diameter::helpers::base::functions::getSessionId(request);
+      if (thisIsAnswer) { // is an answer: try to copy sequence information; alert about Session-Id discrepance
+        anna::diameter::HopByHop hbh = anna::diameter::codec::functions::getHopByHop(referenceRequest);
+        anna::diameter::EndToEnd ete = anna::diameter::codec::functions::getEndToEnd(referenceRequest);
 
-      if (sessionIdRequest != sessionIdAnswer) {
-        s_warn = anna::functions::asString("Sending an answer which Session-Id (%s) is different than supposed corresponding request (%s)", sessionIdAnswer.c_str(), sessionIdRequest.c_str());
-        LOGWARNING(anna::Logger::warning(s_warn, ANNA_FILE_LOCATION));
-        a_testCase->addDebugSummaryHint(s_warn);
+        // Update sequence:
+        anna::diameter::codec::functions::setHopByHop(a_message, hbh);
+        anna::diameter::codec::functions::setEndToEnd(a_message, ete);
+      }
+
+      // Session-Id substitution:
+      std::string thisSessionId = anna::diameter::helpers::base::functions::getSessionId(getMsgDataBlock());
+      if (thisSessionId != sessionIdReferenceRequest) {
+        static anna::diameter::codec::Message codecMsg;
+        codecMsg.decode(getMsgDataBlock());
+        codecMsg.getAvp("Session-Id")->getUTF8String()->setValue(sessionIdReferenceRequest);
+        a_message = codecMsg.code();
+        std::string trace = anna::functions::asString("Replacing %s Session-Id (%s) to set the corresponding request one (%s)", (thisIsAnswer ? "answer":"request"), thisSessionId.c_str(), sessionIdReferenceRequest.c_str());
+        LOGDEBUG(anna::Logger::debug(trace, ANNA_FILE_LOCATION));
+        a_testCase->addDebugSummaryHint(trace);
       }
     }
 
+    // Create comm message:
+    //msg->clearBody();
+    msg->setBody(a_message);
+
+
     if (getType() == Type::Sendxml2e) {
       anna::diameter::comm::ClientSession *usedClientSession = NULL;
 
index c290e17..b925d38 100755 (executable)
@@ -155,7 +155,7 @@ which $TSHARK >/dev/null 2>/dev/null
 
 # Get the frames with diameter content (take care about '-2' two-pass option and don't add it, because we need to get reassembled parts in their corresponding frames):
 # Fields needed (we won't need diameter.hopbyhopid & diameter.endtoendid to verify diameter message as hint patterns; length management will be enough): see https://www.wireshark.org/docs/dfref/d/diameter.html
-FIELDS_DIAMETER="-e diameter.cmd.code -e diameter.flags.request -e diameter.applicationId -e diameter.hopbyhopid -e diameter.endtoendid -e diameter.Session-Id -e diameter.Origin-Host -e diameter.length"
+FIELDS_DIAMETER="-e diameter.cmd.code -e diameter.flags.request -e diameter.applicationId -e diameter.hopbyhopid -e diameter.endtoendid -e diameter.Session-Id -e diameter.Origin-Host -e diameter.Subscription-Id-Data -e diameter.Subscription-Id-Type -e diameter.length"
 FIELDS="-e frame.number -e frame.time_epoch -e ip.src_host -e ip.dst_host $FIELDS_DIAMETER -e tcp.len -e frame.protocols -e tcp.segment"
 # Disect selectors for non-standard diameter ports:
 for port in $OTHER_PORTS
@@ -166,17 +166,17 @@ done
 
 $TSHARK -E separator="|" -r $PCAP_FILE -N mntC -Tfields $FIELDS $DISECT_SELECTORS 2>/dev/null | grep -i diameter > $tmpdir/diameter_frames
 # Example output:
-#                                                                                                      /length\
-# frame     timestamp        src     dst   code R  App-ID   HopByHop   EndToEnd Session-Id Origin-Host DIAM TCP          protocol                    segments 
-#   1           2             3       4     5   6    7         8           9       10          11       12  13              14                          15
-#   1|1427215933.697904000|gt_traf|vcbavipt|272|1|16777238|0x0004e6e6|0x000bd986|xxxxxxx|xxxxxxxxxxxxx|432|432|eth:ip:tcp:diameter:diameter:diameter3gpp|
-#   3|1427215934.449523000|vcbavipt|gt_traf|272|0|16777238|0x0004e6e6|0x000bd986|xxxxxxx|xxxxxxxxxxxxx|292|292|eth:ip:tcp:diameter:diameter:diameter3gpp|
+#                                                                                                                            /length\
+# frame     timestamp        src     dst   code R  App-ID   HopByHop   EndToEnd Session-Id Origin-Host Subs-Data  Subs-Type  DIAM TCP          protocol                    segments 
+#   1           2             3       4     5   6    7         8           9       10          11          12         13      14   15             16                          17
+#   1|1427215933.697904000|gt_traf|vcbavipt|272|1|16777238|0x0004e6e6|0x000bd986|xxxxxxx|xxxxxxxxxxxxx|xxxxxxxxxx|xxxxxxxxxxx|432|432|eth:ip:tcp:diameter:diameter:diameter3gpp|
+#   3|1427215934.449523000|vcbavipt|gt_traf|272|0|16777238|0x0004e6e6|0x000bd986|xxxxxxx|xxxxxxxxxxxxx|xxxxxxxxxx|xxxxxxxxxxx|292|292|eth:ip:tcp:diameter:diameter:diameter3gpp|
 #   5|1427215934.456160000|gt_traf|vcbavipt||||||||1400|eth:ip:tcp:diameter|
-#   6|1427215934.456204000|gt_traf|vcbavipt|265|1|16777236|0x000c73c3|0x0004cee4|xxxxxxx|xxxxxxxxxxxxx|1972|572|eth:ip:tcp:diameter:diameter:diameter3gpp|5,6
-#   8|1427215935.123559000|vcbavipt|gt_traf|265|0|16777236|0x000c73c3|0x0004cee4|xxxxxxx|xxxxxxxxxxxxx|248|248|eth:ip:tcp:diameter:diameter:diameter3gpp|
+#   6|1427215934.456204000|gt_traf|vcbavipt|265|1|16777236|0x000c73c3|0x0004cee4|xxxxxxx|xxxxxxxxxxxxx|xxxxxxxxxx|xxxxxxxxxxx|1972|572|eth:ip:tcp:diameter:diameter:diameter3gpp|5,6
+#   8|1427215935.123559000|vcbavipt|gt_traf|265|0|16777236|0x000c73c3|0x0004cee4|xxxxxxx|xxxxxxxxxxxxx|xxxxxxxxxx|xxxxxxxxxxx|248|248|eth:ip:tcp:diameter:diameter:diameter3gpp|
 all_frames=( $(cat $tmpdir/diameter_frames | cut -d\| -f1) )
-needs_join=( $(cat $tmpdir/diameter_frames | cut -d\| -f15) )
-main_frames=( $(cat $tmpdir/diameter_frames | awk -F\| '{ if ($13 != "") print $1 }') )
+needs_join=( $(cat $tmpdir/diameter_frames | cut -d\| -f17) )
+main_frames=( $(cat $tmpdir/diameter_frames | awk -F\| '{ if ($15 != "") print $1 }') )
 
 # Reassemble procedure (using frame 1 as example):
 # (for non segmented frames, it is enough with tcp or diameter length within the frame content itself)
@@ -191,7 +191,7 @@ for frame in ${all_frames[@]}; do
   frame_info=$(grep "^${frame}|" $tmpdir/diameter_frames)
 
   # Get the diameter part:
-  tcp_len=$(echo $frame_info | cut -d\| -f13)
+  tcp_len=$(echo $frame_info | cut -d\| -f15)
   frm_len=$(wc -c $tmpdir/block.$frame | awk '{ print $1 }')
   cut_len=$((frm_len-2*tcp_len))
   cat $tmpdir/block.$frame | cut -c${cut_len}- > $RESULTS_DIR/$frame.hex
@@ -207,6 +207,11 @@ for frame in ${all_frames[@]}; do
   appid=$(echo $frame_info | cut -d\| -f7)
   sid=$(echo $frame_info | cut -d\| -f10)
   oh=$(echo $frame_info | cut -d\| -f11)
+  subscriber=$(echo $frame_info | cut -d\| -f12)
+  subscribertype=$(echo $frame_info | cut -d\| -f13)
+  [ "$subscribertype" = "0" ] && subscribertype=msisdn
+  [ "$subscribertype" = "1" ] && subscribertype=imsi
+
   #hbh=$(echo $frame_info | cut -d\| -f8)
   #e2e=$(echo $frame_info | cut -d\| -f9)
   # HBH and ETE To decimal:
@@ -221,6 +226,11 @@ for frame in ${all_frames[@]}; do
   echo "applicationid=$appid" >> $RESULTS_DIR/$frame.metadata
   [ -n "$sid" ] && echo "sessionid=$sid" >> $RESULTS_DIR/$frame.metadata
   echo "originhost=$oh" >> $RESULTS_DIR/$frame.metadata
+  if [ -n "$subscriber" ]
+  then
+    echo "subscriber=$subscriber" >> $RESULTS_DIR/$frame.metadata
+    echo "subscribertype=$subscribertype" >> $RESULTS_DIR/$frame.metadata
+  fi
   #echo "hopbyhop=$hbh" >> $RESULTS_DIR/$frame.metadata
   #echo "endtoend=$e2e" >> $RESULTS_DIR/$frame.metadata
 
@@ -239,7 +249,7 @@ done
 
 # Delete superfluous metadata:
 echo "Deleting superfluous buffers & metadata ..."
-segments=( $(cat $tmpdir/diameter_frames | awk -F\| '{ if ($12 == "") print $1 }') )
+segments=( $(cat $tmpdir/diameter_frames | awk -F\| '{ if ($14 == "") print $1 }') )
 for s in ${segments[@]}; do rm $RESULTS_DIR/$s.*; done
 
 # Detecting Session-Id values: