SEMS node installation
Install packages
# apt update && apt install sems sems-modules-yetiConfiguration files
/etc/sems/sems.conf
Add new Point of Presence using web interface. Use id of newly created PoP as value for pop_id parameter.
Add new Node using web interface. Use id of newly created Node as value for node_id parameter.
Replace <SIGNALLING_IP>, <MEDIA_IP> with correct values for your server :
general {
stderr = no
syslog_loglevel = 2
syslog_facility = LOCAL0
node_id = 1
shutdown_mode {
code = 508
reason = "Yeti node in shutdown mode"
allow_uac = true
}
media_processor_threads = 4
rtp_receiver_threads = 4
session_processor_threads = 20
sip_udp_server_threads = 2
sip_tcp_server_threads = 2
dead_rtp_time = 30
default_bl_ttl = 0
symmetric_rtp_mode = packets
symmetric_rtp_packets = 20
}
signaling-interfaces {
interface primary {
default-media-interface = primary
ip4 {
sip-udp {
address = <SIGNALLING_IP>
port = 5060
use-raw-sockets = off
}
sip-tcp {
address = <SIGNALLING_IP>
port = 5060
connect-timeout = 2000
static-client-port = on
idle-timeout=900000
use-raw-sockets = off
}
}
}
}
media-interfaces {
interface primary {
ip4 {
rtp {
address = <MEDIA_IP>
low-port = 16384
high-port = 32769
dscp = 46
use-raw-sockets = off
}
}
}
}
modules {
module "di_log" {}
module "mp3" {}
module "opus" {}
module "wav" {}
module "gsm" {}
module "ilbc" {}
module "adpcm" {}
module "l16" {}
module "g722" {}
module "registrar_client" {}
module "postgresql" {}
module "session_timer" {}
module "jsonrpc" {
listen{
address = 127.0.0.1
port = 7080
}
server_threads = 1
map(yeti.request.registrations.reload, yeti.request.db_states.reload)
map(yeti.request.router.translations.reload, yeti.request.db_states.reload)
map(yeti.request.router.codec-groups.reload, yeti.request.db_states.reload)
map(yeti.request.sensors.reload, yeti.request.db_states.reload)
map(yeti.request.radius.authorization.profiles.reload, yeti.request.db_states.reload)
map(yeti.request.radius.accounting.profiles.reload, yeti.request.db_states.reload)
map(yeti.request.auth.credentials.reload, yeti.request.db_states.reload)
map(yeti.request.options_prober.reload, yeti.request.db_states.reload)
}
module "http_client" {}
module-global "uac_auth" {}
module "options_prober" {}
module "radius_client" {}
module "redis" {
max_batch_size = 10
batch_timeout = 100
max_queue_size = 1000
}
module "registrar" {
redis {
write {
hosts = { 127.0.0.1:6379 }
}
read {
hosts = { 127.0.0.1:6379 }
}
}
headers = { x-orig-ip, x-orig-port, x-orig-proto, x-orig-lat, x-orig-lon }
}
module "yeti" {
pop_id = <POP_ID>
lega_cdr_headers {
add_q850_reason = yes
header(x-yeti-auth, string)
header(x-orig-ip, string)
header(x-orig-port, string)
header(x-orig-proto, string)
header(x-orig-lat, string)
header(x-orig-lon, string)
header(p-charge-info, string, p_charge_info_in, String)
header(diversion, array)
header(p-asserted-identity, array)
header(p-preferred-identity, string)
header(privacy, array)
header(remote-party-id, array)
header(rpid-privacy, array)
}
legb_cdr_headers {
header(diversion, array)
header(p-asserted-identity, array)
header(p-preferred-identity, string)
header(privacy, array)
header(remote-party-id, array)
header(rpid-privacy, array)
}
legb_response_cdr_headers {
add_q850_reason = yes
}
write_internal_disconnect_code = yes
auth {
realm = yeti-switch
}
msg_logger_dir = /var/spool/sems/dump
audio_recorder_dir = /var/spool/sems/records
audio_recorder_compress = false
db_refresh_interval = 5
ip_auth_reject_if_no_matched = true
routing {
schema = switch22
function = route_release
init = init
pass_input_interface_name = true
new_codec_groups = true
master_pool {
host = 127.0.0.1
port = 5432
name = yeti
user = yeti
pass = somepassword
size = 4
check_interval = 10
statement_timeout = 3000
}
failover_to_slave = false
slave_pool {
host = 127.0.0.1
port = 5432
name = yeti
user = yeti
pass = somepassword
size = 4
check_interval = 10
statement_timeout = 3000
}
}
cdr {
pool_size = 2
auth_pool_size = 2
schema = switch
function = writecdr
master {
host = 127.0.0.1
port = 5432
name = cdr
user = cdr
pass = somepassword
}
failover_to_slave = false
slave {
host = 127.0.0.1
port = 5432
name = cdr
user = cdr
pass = somepassword
}
batch_size = 1
batch_timeout = 5000
auth_batch_size = 1
auth_batch_timeout = 20000
}
resources {
reject_on_error = false
write {
hosts = { 127.0.0.1:6379 }
timeout = 500
}
read {
hosts = { 127.0.0.1:6379 }
timeout = 1000
}
}
rpc {
calls_show_limit = 10000
}
}
}
routing {
application = yeti
}WARNING
JRPC interface allows shutdown SEMS node or make it non-operational. JRPC interface should be secured by firewall to prevent connections from not trusted hosts. In YETI systems only two components should have ability to connect to RPC - WEB interface and yeti-cli console
Launch traffic switch
Launch configured traffic switch instance:
# systemctl start semsIn case of errors it's useful to use sems -E -D3 command which will launch daemon in foreground with debug logging level
Checks
Check if sems process exists and signaling/media/rpc sockets are opened:
# systemctl status sems
● sems.service - SEMS for YETI project
Loaded: loaded (/lib/systemd/system/sems.service; enabled; preset: enabled)
Active: active (running) since Thu 2024-12-05 20:21:52 UTC; 5 days ago
Docs: https://yeti-switch.org/docs/
Main PID: 68166 (sems)
Tasks: 84 (limit: 154132)
Memory: 3.3G
CPU: 2d 18h 15min 51.113s
CGroup: /system.slice/sems.service
└─68166 /usr/bin/sems -f /etc/sems/sems.conf
# pgrep sems
29749
# netstat -lpn | grep sems
tcp 0 0 127.0.0.1:8090 0.0.0.0:* LISTEN 29749/sems
udp 0 0 127.0.0.1:5061 0.0.0.0:* 29749/sems
raw 2688 0 0.0.0.0:17 0.0.0.0:* 7 29749/semsCheck logs using for possible errors:
# journalctl -u sems