diff --git a/lib/database.py b/lib/database.py index b641570..ca19437 100755 --- a/lib/database.py +++ b/lib/database.py @@ -29,7 +29,7 @@ class APN(Base): __tablename__ = 'apn' apn_id = Column(Integer, primary_key=True, doc='Unique ID of APN') apn = Column(String(50), nullable=False, doc='Short name of the APN') - ip_version = Column(Integer, default=0, doc="IP version used - 0: ipv4, 1: ipv6 2: ipv4+6 3: ipv4 or ipv6 [3GPP TS 29.272 7.3.62]") + ip_version = Column(Integer, default=0, doc="IP version used - 0: ipv4, 1: ipv6 2: ipv4+6 3: ipv4 or ipv6 4: [3GPP TS 29.272 7.3.62]") pgw_address = Column(String(50), doc='IP of the PGW') sgw_address = Column(String(50), doc='IP of the SGW') charging_characteristics = Column(String(4), default='0800', doc='For the encoding of this information element see 3GPP TS 32.298 [9]') @@ -40,6 +40,12 @@ class APN(Base): arp_preemption_capability = Column(Boolean, default=False, doc='Allocation and Retention Policy - Capability to Preempt resources from other Subscribers') arp_preemption_vulnerability = Column(Boolean, default=True, doc='Allocation and Retention Policy - Vulnerability to have resources Preempted by other Subscribers') charging_rule_list = Column(String(18), doc='Comma separated list of predefined ChargingRules to be installed in CCA-I') + nbiot = Column(Boolean, default=0, doc="Whether this APN provides NBIoT") + nidd_scef_id = Column(String(512), default=None, doc="ID of SCEF to be used for NIDD for NB-IoT") + nidd_scef_realm = Column(String(512), default=None, doc='Realm of the SCEF for NIDD for NB-IoT') + nidd_mechanism = Column(Integer, default=None, doc="Mechanism used to transfer Non-IP-Data: SGi-BASED-DATA-DELIVERY (0) or SCEF-BASED-DATA-DELIVERY (1)") + nidd_rds = Column(Integer, default=None, doc="Indicates if Reliable Data Service is enabled or disabled for this APN: DISABLED (0) or ENABLED (1)") + nidd_preferred_data_mode = Column(Integer, default=None, doc="Preferred-Data-Mode: Data over User Plane Preferred (0) or Data over Control Plane Preferred (1)") last_modified = Column(String(100), default=datetime.datetime.now(tz=timezone.utc), doc='Timestamp of last modification') operation_logs = relationship("APN_OPERATION_LOG", back_populates="apn") diff --git a/lib/diameter.py b/lib/diameter.py index f1ec9da..ccec483 100644 --- a/lib/diameter.py +++ b/lib/diameter.py @@ -1291,7 +1291,54 @@ def Answer_16777251_316(self, packet_vars, avps): #Sub AVPs of APN Configuration Profile APN_context_identifer = self.generate_vendor_avp(1423, "c0", 10415, self.int_to_hex(APN_context_identifer_count, 4)) APN_PDN_type = self.generate_vendor_avp(1456, "c0", 10415, self.int_to_hex(int(apn_data['ip_version']), 4)) + NIDD_Parameters = '' + try: + nbIotEnabled = apn_data.get('nbiot', False) + #If int(apn_data['ip_version']) == 4 (Non-IP) then this is NB-IoT and we need to add the NB-IoT specific parameters + if nbIotEnabled and int(apn_data['ip_version']) == 4: + + #Add Non-IP-PDN-Type-Indicator + NIDD_Parameters = NIDD_Parameters + self.generate_vendor_avp(1681, "c0", 10415, self.int_to_hex(1), 4) + + #Add SCEF ID + try: + NIDD_Parameters = NIDD_Parameters + self.generate_vendor_avp(3125, "c0", 10415, self.string_to_hex(str(apn_data['nidd_scef_id']))) + except: + pass + + #Add SCEF Realm + try: + #Check SCEF Realm is not empty + if apn_data['nidd_scef_realm'] != '': + NIDD_Parameters = NIDD_Parameters + self.generate_vendor_avp(1684, "c0", 10415, self.string_to_hex(str(apn_data['nidd_scef_realm']))) + except: + pass + + #Add Reliable Data Indicator + try: + NIDD_Parameters = NIDD_Parameters + self.generate_vendor_avp(1697, "c0", 10415, self.int_to_hex(int(apn_data['nidd_rds']), 4)) + except: + pass + + #Add Preferred Data Mode + try: + NIDD_Parameters = NIDD_Parameters + self.generate_vendor_avp(1686, "c0", 10415, self.int_to_hex(int(apn_data['nidd_preferred_data_mode']), 4)) + except: + pass + + #Add Non-IP-Data-Delivery-Mechanism + try: + NIDD_Parameters = NIDD_Parameters + self.generate_vendor_avp(1682, "c0", 10415, self.int_to_hex(int(apn_data['nidd_mechanism']), 4)) + except: + pass + + else: + NIDD_Parameters = '' + + except Exception as e: + self.logTool.log(service='HSS', level='error', message=f"Error preparing NIDD parameters: {traceback.format_exc()}", redisClient=self.redisMessaging) + self.logTool.log(service='HSS', level='debug', message="Setting APN AMBR", redisClient=self.redisMessaging) #AMBR AMBR = '' #Initiate empty var AVP for AMBR @@ -1345,7 +1392,7 @@ def Answer_16777251_316(self, packet_vars, avps): MIP6_Agent_Info = '' APN_Configuration_AVPS = APN_context_identifer + APN_PDN_type + APN_AMBR + APN_Service_Selection \ - + APN_EPS_Subscribed_QoS_Profile + Served_Party_Address + MIP6_Agent_Info + PDN_GW_Allocation_Type + VPLMN_Dynamic_Address_Allowed + + APN_EPS_Subscribed_QoS_Profile + Served_Party_Address + MIP6_Agent_Info + PDN_GW_Allocation_Type + VPLMN_Dynamic_Address_Allowed + NIDD_Parameters APN_Configuration += self.generate_vendor_avp(1430, "c0", 10415, APN_Configuration_AVPS) @@ -3594,4 +3641,4 @@ def Request_16777252_324(self, imei, imsi): response = self.generate_diameter_packet("01", "c0", 324, 16777252, self.generate_id(4), self.generate_id(4), avp) #Generate Diameter packet - return response \ No newline at end of file + return response