diff --git a/README.md b/README.md
index f2338b84..ef629e42 100644
--- a/README.md
+++ b/README.md
@@ -43,6 +43,8 @@ core networks.
colte packages. This should be installed automatically as a dependency via apt
if any of the other component packages are installed.
+
+
## Apt Packages
To ease deployment, we host pre-compiled apt packages on our server for x86_64
@@ -51,19 +53,42 @@ repository to get colte and haulage, and you will also need to add the open5gs
repository separately. To do this, use the following commands according to your
distribution:
-### Debian 10 (buster) (**Recommended**)
+## Nodejs version recommendations
+A Ubuntu/Debian basic installation use nodejs at version 10, open5gs and CoLTE need
+nodejs version 14 or latest (this solve npm takes long time to install), so we need to install it following next steps:
+```shell
+sudo apt update
+sudo apt install curl
+curl -fsSL https://deb.nodesource.com/setup_21.x | sudo -E bash -
+sudo apt install nodejs
+```
+
+MongoDB v6 is the latest version that open5gs uses.
+
+### Debian 10 (buster) (**Recommended**)
```shell
echo "deb [signed-by=/usr/share/keyrings/colte-archive-keyring.gpg] http://colte.cs.washington.edu $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/colte.list
sudo wget -O /usr/share/keyrings/colte-archive-keyring.gpg http://colte.cs.washington.edu/colte-archive-keyring.gpg
-wget -qO - https://www.mongodb.org/static/pgp/server-4.2.asc | sudo apt-key add -
-echo "deb http://repo.mongodb.org/apt/debian buster/mongodb-org/4.2 main" | sudo tee /etc/apt/sources.list.d/mongodb-org.list
+curl -fsSL https://pgp.mongodb.com/server-6.0.asc | sudo gpg -o /usr/share/keyrings/mongodb-server-6.0.gpg --dearmor
+echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-6.0.gpg] https://repo.mongodb.org/apt/debian bullseye/mongodb-org/6.0 main" | sudo tee /etc/apt/sources.list.d/mongodb-org-6.0.list
+sudo apt update
+sudo apt upgrade -y
+sudo apt install -y mongodb-org
+sudo systemctl start mongod
+sudo systemctl enable mongod
wget -qO - https://download.opensuse.org/repositories/home:/acetcom:/open5gs:/latest/Debian_10/Release.key | sudo apt-key add -
sudo sh -c "echo 'deb http://download.opensuse.org/repositories/home:/acetcom:/open5gs:/latest/Debian_10/ ./' > /etc/apt/sources.list.d/open5gs.list"
sudo apt update
sudo apt install colte-cn-4g colte-prepaid
```
+You can install under Debian 11
+```shell
+wget -qO - https://download.opensuse.org/repositories/home:/acetcom:/open5gs:/latest/Debian_10/Release.key | sudo apt-key add -
+sudo sh -c "echo 'deb http://download.opensuse.org/repositories/home:/acetcom:/open5gs:/latest/Debian_11/ ./' > /etc/apt/sources.list.d/open5gs.list"
+```
+
### Ubuntu 18.04 or 20.04 (bionic or focal)
```shell
@@ -91,6 +116,8 @@ npm install
npm start
```
+If you want to use a translated template, at the directory views/ from each web interface, you need to change the .hbs-es files to .hbs
+
# Configuration
After installation, pointers to all the various config files can be found in `/etc/colte/`. The main config file is `config.yml`. After you edit this file, run `colteconf` to reconfigure all components and restart them as necessary. Note that you **must** run colteconf at least once after installing CoLTE, because there is no way for us to know some of the options (e.g. upstream and downstream interfaces).
diff --git a/conf/open5gs_dbconf.sh b/conf/open5gs_dbconf.sh
index 1e3b0ff2..129f1cd3 100755
--- a/conf/open5gs_dbconf.sh
+++ b/conf/open5gs_dbconf.sh
@@ -12,6 +12,7 @@ display_help() {
echo " static_ip6 {imsi ip6}: adds a static IPv6 assignment to an already-existing user"
echo " type {imsi type}: changes the PDN-Type of the first PDN: 0 = IPv4, 1 = IPv6, 2 = IPv4v6, 3 = v4 OR v6"
echo " help: displays this message and exits"
+ echo " speed {imsi dl_value dl_unit ul_value ul_unit}: dl_unit 0=bps 1=Kbps 2=Mbps 3=Gbps 4=Tbps "
echo " default values are as follows: APN \"internet\", dl_bw/ul_bw 1 Gbps, PGW address is 127.0.0.3, IPv4 only"
}
@@ -283,4 +284,19 @@ if [ "$1" = "type" ]; then
exit 0
fi
+if [ "$1" = "speed" ]; then
+ if [ "$#" -ne 6 ]; then
+ echo "dbconf.sh: incorrect number of args, format is \"open5gs_dbconf.sh speed imsi dl_value dl_unit_value ul_value ul_unit_value \""
+ exit 1
+ fi
+ IMSI=$2
+ DL_VALUE=$3
+ DL_UNIT=$4
+ UL_VALUE=$5
+ UL_UNIT=$6
+ mongo --eval "db.subscribers.update({\"imsi\": \"$IMSI\"},{\$set : { \"ambr\": {\"downlink\": {\"value\": NumberInt($DL_VALUE), \"unit\": NumberInt($DL_UNIT)}, \"uplink\": {\"value\": NumberInt($UL_VALUE),\"unit\": ($UL_UNIT) } } }});" open5gs
+ exit 0
+fi
+
+
display_help
diff --git a/python/colteconf_cn_4g.py b/python/colteconf_cn_4g.py
index 3cb809a9..227f9331 100644
--- a/python/colteconf_cn_4g.py
+++ b/python/colteconf_cn_4g.py
@@ -126,41 +126,43 @@ def _update_mme(colte_data):
with open(mme, "r+") as file:
mme_data = yaml.load(file.read())
-
+ yaml.dump(mme_data['mme']['gummei'][0]['plmn_id'], sys.stdout)
+ print ("MMC",mme_data['mme']['gummei'][0]['plmn_id']['mcc'])
+ print (mme_data['mme']['gummei'][0]['plmn_id']['mnc'])
+ #print (len(mme_data['mme']['gummei']['plmn_id']))
# Create fields in the data if they do not yet exist
_create_field_if_not_exist(mme_data, ["mme"], CommentedMap())
_create_field_if_not_exist(mme_data, ["mme", "gummei"], CommentedMap())
- _create_field_if_not_exist(
- mme_data, ["mme", "gummei", "plmn_id"], CommentedMap()
- )
- mme_data["mme"]["gummei"]["plmn_id"]["mcc"] = colte_data["mcc"]
- mme_data["mme"]["gummei"]["plmn_id"]["mnc"] = colte_data["mnc"]
+ _create_field_if_not_exist(mme_data, ['mme','gummei',0,'plmn_id'], CommentedMap())
+
+ mme_data["mme"]["gummei"][0]["plmn_id"]["mcc"] = colte_data["mcc"]
+ mme_data["mme"]["gummei"][0]["plmn_id"]["mnc"] = colte_data["mnc"]
_create_field_if_not_exist(mme_data, ["mme", "tai"], CommentedMap())
- _create_field_if_not_exist(mme_data, ["mme", "tai", "plmn_id"], CommentedMap())
- mme_data["mme"]["tai"]["plmn_id"]["mcc"] = colte_data["mcc"]
- mme_data["mme"]["tai"]["plmn_id"]["mnc"] = colte_data["mnc"]
+ _create_field_if_not_exist(mme_data, ["mme", "tai",0, "plmn_id"], CommentedMap())
+ mme_data["mme"]["tai"][0]["plmn_id"]["mcc"] = colte_data["mcc"]
+ mme_data["mme"]["tai"][0]["plmn_id"]["mnc"] = colte_data["mnc"]
- mme_data["mme"]["s1ap"] = CommentedSeq()
- mme_data["mme"]["s1ap"].append({"addr": colte_data["enb_iface_addr"]})
+ _create_field_if_not_exist(mme_data, ["mme", "s1ap"], CommentedMap())
+ mme_data["mme"]["s1ap"]["server"] = CommentedSeq()
+ mme_data["mme"]["s1ap"]["server"].append({"address": colte_data["enb_iface_addr"]})
_create_field_if_not_exist(mme_data, ["mme", "network_name"], CommentedMap())
mme_data["mme"]["network_name"]["full"] = colte_data["network_name"]
- mme_data["mme"]["gtpc"] = CommentedSeq()
- mme_data["mme"]["gtpc"].append({"addr": "127.0.0.2"})
+ _create_field_if_not_exist(mme_data, ["mme", "gtpc"], CommentedMap())
+ mme_data["mme"]["gtpc"]["server"] = CommentedSeq()
+ mme_data["mme"]["gtpc"]["server"].append({"address": "127.0.0.2"})
- _create_field_if_not_exist(mme_data, ["sgwc"], CommentedMap())
+ _create_field_if_not_exist(mme_data, ["mme", "gtpc", "client"], CommentedMap())
- mme_data["sgwc"]["gtpc"] = CommentedSeq()
- mme_data["sgwc"]["gtpc"].append({"addr": "127.0.0.3"})
+ mme_data["mme"]["gtpc"]["client"]["sgwc"] = CommentedSeq()
+ mme_data["mme"]["gtpc"]["client"]["sgwc"].append({"address": "127.0.0.3"})
- _create_field_if_not_exist(mme_data, ["smf"], CommentedMap())
-
- mme_data["smf"]["gtpc"] = CommentedSeq()
- mme_data["smf"]["gtpc"].append({"addr": "127.0.0.4"})
- mme_data["smf"]["gtpc"].append({"addr": "::1"})
+ mme_data["mme"]["gtpc"]["client"]["smf"] = CommentedSeq()
+ mme_data["mme"]["gtpc"]["client"]["smf"].append({"address": "127.0.0.4"})
+ mme_data["mme"]["gtpc"]["client"]["smf"].append({"address": "::1"})
# Disable internal file logging since journald is capturing stdout
_create_field_if_not_exist(mme_data, ["logger"], CommentedMap())
@@ -194,17 +196,18 @@ def _update_sgwc(colte_data):
# Create fields in the data if they do not yet exist
_create_field_if_not_exist(sgwc_data, ["sgwc"], CommentedMap())
- sgwc_data["sgwc"]["gtpc"] = CommentedSeq()
- sgwc_data["sgwc"]["gtpc"].append({"addr": "127.0.0.3"})
+ _create_field_if_not_exist(sgwc_data, ["sgwc", "gtpc"], CommentedMap())
+ sgwc_data["sgwc"]["gtpc"]["server"] = CommentedSeq()
+ sgwc_data["sgwc"]["gtpc"]["server"].append({"address": "127.0.0.3"})
- sgwc_data["sgwc"]["pfcp"] = CommentedSeq()
- sgwc_data["sgwc"]["pfcp"].append({"addr": "127.0.0.3"})
+ _create_field_if_not_exist(sgwc_data, ["sgwc", "pfcp"], CommentedMap())
+ sgwc_data["sgwc"]["pfcp"]["server"] = CommentedSeq()
+ sgwc_data["sgwc"]["pfcp"]["server"].append({"address": "127.0.0.3"})
# Link towards the SGW-U
- _create_field_if_not_exist(sgwc_data, ["sgwu"], CommentedMap())
-
- sgwc_data["sgwu"]["pfcp"] = CommentedSeq()
- sgwc_data["sgwu"]["pfcp"].append({"addr": "127.0.0.6"})
+ _create_field_if_not_exist(sgwc_data, ["sgwc", "pfcp", "client"], CommentedMap())
+ sgwc_data["sgwc"]["pfcp"]["client"]["sgwu"] = CommentedSeq()
+ sgwc_data["sgwc"]["pfcp"]["client"]["sgwu"].append({"address": "127.0.0.6"})
# Disable internal file logging since journald is capturing stdout
_create_field_if_not_exist(sgwc_data, ["logger"], CommentedMap())
@@ -223,11 +226,13 @@ def _update_sgwu(colte_data):
# Create fields in the data if they do not yet exist
_create_field_if_not_exist(sgwu_data, ["sgwu"], CommentedMap())
- sgwu_data["sgwu"]["gtpu"] = CommentedSeq()
- sgwu_data["sgwu"]["gtpu"].append({"addr": colte_data["enb_iface_addr"]})
+ _create_field_if_not_exist(sgwu_data, ["sgwu", "gtpu"], CommentedMap())
+ sgwu_data["sgwu"]["gtpu"]["server"] = CommentedSeq()
+ sgwu_data["sgwu"]["gtpu"]["server"].append({"address": colte_data["enb_iface_addr"]})
- sgwu_data["sgwu"]["pfcp"] = CommentedSeq()
- sgwu_data["sgwu"]["pfcp"].append({"addr": "127.0.0.6"})
+ _create_field_if_not_exist(sgwu_data, ["sgwu", "pfcp"], CommentedMap())
+ sgwu_data["sgwu"]["pfcp"]["server"] = CommentedSeq()
+ sgwu_data["sgwu"]["pfcp"]["server"].append({"address": "127.0.0.6"})
# Link towards the SGW-C
# TODO(matt9j) This might be the wrong address! Not included in the default
@@ -251,30 +256,33 @@ def _update_smf(colte_data):
# Create fields in the data if they do not yet exist
_create_field_if_not_exist(smf_data, ["smf"], CommentedMap())
- smf_data["smf"]["gtpc"] = CommentedSeq()
- smf_data["smf"]["gtpc"].append({"addr": "127.0.0.4"})
- smf_data["smf"]["gtpc"].append({"addr": "::1"})
+ _create_field_if_not_exist(smf_data, ["smf", "gtpc"], CommentedMap())
+ smf_data["smf"]["gtpc"]["server"] = CommentedSeq()
+ smf_data["smf"]["gtpc"]["server"].append({"address": "127.0.0.4"})
+ smf_data["smf"]["gtpc"]["server"].append({"address": "::1"})
- smf_data["smf"]["pfcp"] = CommentedSeq()
- smf_data["smf"]["pfcp"].append({"addr": "127.0.0.4"})
- smf_data["smf"]["pfcp"].append({"addr": "::1"})
+ _create_field_if_not_exist(smf_data, ["smf", "pfcp"], CommentedMap())
+ smf_data["smf"]["pfcp"]["server"] = CommentedSeq()
+ smf_data["smf"]["pfcp"]["server"].append({"address": "127.0.0.4"})
+ smf_data["smf"]["pfcp"]["server"].append({"address": "::1"})
- smf_data["smf"]["subnet"] = CommentedSeq()
+ # Create link to UPF
+ _create_field_if_not_exist(smf_data, ["smf", "pfcp", "client"], CommentedMap())
+
+ smf_data["smf"]["pfcp"]["client"]["upf"] = CommentedSeq()
+ smf_data["smf"]["pfcp"]["client"]["upf"].append({"address": "127.0.0.7"})
+
+ # Add Subnets, DNS, and MTU
+ smf_data["smf"]["session"] = CommentedSeq()
net = IPNetwork(colte_data["lte_subnet"])
netstr = str(net[1]) + "/" + str(net.prefixlen)
- smf_data["smf"]["subnet"].append({"addr": netstr})
+ smf_data["smf"]["session"].append({"subnet": netstr})
smf_data["smf"]["dns"] = CommentedSeq()
smf_data["smf"]["dns"].append(colte_data["dns"])
smf_data["smf"]["mtu"] = 1400
- # Create link to UPF
- _create_field_if_not_exist(smf_data, ["upf"], CommentedMap())
-
- smf_data["upf"]["pfcp"] = CommentedSeq()
- smf_data["upf"]["pfcp"].append({"addr": "127.0.0.7"})
-
# Disable 5GC NRF link while operating EPC only
if "nrf" in smf_data:
del smf_data["nrf"]
@@ -296,16 +304,18 @@ def _update_upf(colte_data):
# Create fields in the data if they do not yet exist
_create_field_if_not_exist(upf_data, ["upf"], CommentedMap())
- upf_data["upf"]["pfcp"] = CommentedSeq()
- upf_data["upf"]["pfcp"].append({"addr": "127.0.0.7"})
+ _create_field_if_not_exist(upf_data, ["upf", "pfcp"], CommentedMap())
+ upf_data["upf"]["pfcp"]["server"] = CommentedSeq()
+ upf_data["upf"]["pfcp"]["server"].append({"address": "127.0.0.7"})
- upf_data["upf"]["gtpu"] = CommentedSeq()
- upf_data["upf"]["gtpu"].append({"addr": "127.0.0.7"})
+ _create_field_if_not_exist(upf_data, ["upf", "gtpu"], CommentedMap())
+ upf_data["upf"]["gtpu"]["server"] = CommentedSeq()
+ upf_data["upf"]["gtpu"]["server"].append({"address": "127.0.0.7"})
- upf_data["upf"]["subnet"] = CommentedSeq()
+ upf_data["upf"]["session"] = CommentedSeq()
net = IPNetwork(colte_data["lte_subnet"])
netstr = str(net[1]) + "/" + str(net.prefixlen)
- upf_data["upf"]["subnet"].append({"addr": netstr})
+ upf_data["upf"]["session"].append({"subnet": netstr})
# Link to the SMF
# TODO(matt9j) Might not be needed
@@ -368,5 +378,4 @@ def _control_epc_services(action):
# Restart everything to pick up new configurations, and don't restart
# networkd while the EPC or metering are running.
stop_all_services()
- os.system("systemctl restart systemd-networkd")
- sync_service_state(colte_data)
+ os.system("systemctl restart systemd-networkd")
\ No newline at end of file
diff --git a/python/coltedb.py b/python/coltedb.py
index 5044709a..effb614f 100644
--- a/python/coltedb.py
+++ b/python/coltedb.py
@@ -20,6 +20,8 @@ def display_help():
print(" topup_data {imsi} {data}: adds bytes to a user's account")
print(" admin {imsi}: gives a user administrative privileges")
print(" noadmin {imsi}: removes a user's administrative privileges")
+ print(" speed {imsi dl_value dl_unit ul_value ul_unit}: Change bandwith per UE unit values 0=bps 1=Kbps 2=Mbps 3=Gbps 4=Tbps")
+ print(" default values are as follows: APN \"internet\", dl_bw/ul_bw 1 Gbps, PGW address is 127.0.0.3, IPv4 only ")
print(" help: displays this message and exits")
@@ -212,5 +214,21 @@ def display_help():
db_name=dbname, db_user=db_user, db_pass=db_pass, imsi=sys.argv[2]
)
+ elif command == "speed":
+ if len(sys.argv) != 7 :
+ log.error(
+ 'coltedb: incorrect number of args, format is "coltedb speed imsi dl_value dl_unit ul_value dl_unit units values are 0=bps 1=Kbps 2=Mbps 3=Gbps 4=Gbps"'
+ )
+ else:
+ if core_network is not None:
+ core_network.speed_user(
+ imsi=sys.argv[2],
+ dl_value=sys.argv[3],
+ dl_unit=sys.argv[4],
+ ul_value=sys.argv[5],
+ ul_unit=sys.argv[6],
+ )
+
+
else:
display_help()
diff --git a/python/coltedb_cn_4g.py b/python/coltedb_cn_4g.py
index a539d897..6ace60aa 100644
--- a/python/coltedb_cn_4g.py
+++ b/python/coltedb_cn_4g.py
@@ -16,6 +16,9 @@ def add_user(imsi, ip, ki, opc, apn):
def remove_user(imsi):
subprocess.run(["/etc/colte/colte_open5gsdb", "remove", str(imsi)], check=True)
+def speed_user(imsi, dl_value, dl_unit, ul_value, ul_unit):
+ open5gs_entry = [str(imsi), str(dl_value), str(dl_unit), str(ul_value), str(ul_unit)]
+ subprocess.run(["/etc/colte/colte_open5gsdb", "speed"] + open5gs_entry, check=True)
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
diff --git a/webadmin/views/home.hbs-es b/webadmin/views/home.hbs-es
new file mode 100644
index 00000000..3dd1ea35
--- /dev/null
+++ b/webadmin/views/home.hbs-es
@@ -0,0 +1,71 @@
+
| IMSI | +Nombre | +Numero telefonico | +Saldo de Datos | +Saldo en pesos | +Acceso a Internet | +Acceso Local -CoLTE | +
|---|---|---|---|---|---|---|
{{translate "Saldo actual: $"}}{{{renderCurrency balance}}}
+{{translate "Datos Disponibles: "}}{{data_balance_str}}
++ +
+{{translate "Número de Teléfono"}}: {{msisdn}}
+{{translate "Saldo Actual: $"}}{{{renderCurrency balance}}}
+{{translate "Datos Disponibles: "}}{{data_balance_str}}
+{{translate "Total Descarga: "}}{{raw_down_str}}
+{{translate "Total Enviado: "}}{{raw_up_str}}
+{{translate "Saldo actual: $"}}{{{renderCurrency balance}}}
+ +