From d3aa79427c109d5ae9c2e63dfead6886daa257a0 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 9 Oct 2017 11:01:13 +0100 Subject: [PATCH 001/172] Initial commit with docs to start new branch --- srsepc/CMakeLists.txt | 50 ++ srsepc/docs/.gitignore | 1 + srsepc/docs/Makefile | 216 +++++++ srsepc/docs/README | 7 + srsepc/docs/source/_imgs/epc-auth-plane.svg | 289 +++++++++ .../docs/source/_imgs/epc-control-plane.svg | 598 ++++++++++++++++++ srsepc/docs/source/_imgs/epc-overall.svg | 381 +++++++++++ srsepc/docs/source/_imgs/epc-user-plane.svg | 388 ++++++++++++ srsepc/docs/source/_static/.gitignore | 0 srsepc/docs/source/_templates/.gitignore | 0 srsepc/docs/source/conf.py | 283 +++++++++ srsepc/docs/source/epc_design.rst | 50 ++ srsepc/docs/source/epc_overview.rst | 225 +++++++ srsepc/docs/source/epc_usage.rst | 2 + srsepc/docs/source/index.rst | 18 + 15 files changed, 2508 insertions(+) create mode 100644 srsepc/CMakeLists.txt create mode 100644 srsepc/docs/.gitignore create mode 100644 srsepc/docs/Makefile create mode 100644 srsepc/docs/README create mode 100644 srsepc/docs/source/_imgs/epc-auth-plane.svg create mode 100644 srsepc/docs/source/_imgs/epc-control-plane.svg create mode 100644 srsepc/docs/source/_imgs/epc-overall.svg create mode 100644 srsepc/docs/source/_imgs/epc-user-plane.svg create mode 100644 srsepc/docs/source/_static/.gitignore create mode 100644 srsepc/docs/source/_templates/.gitignore create mode 100644 srsepc/docs/source/conf.py create mode 100644 srsepc/docs/source/epc_design.rst create mode 100644 srsepc/docs/source/epc_overview.rst create mode 100644 srsepc/docs/source/epc_usage.rst create mode 100644 srsepc/docs/source/index.rst diff --git a/srsepc/CMakeLists.txt b/srsepc/CMakeLists.txt new file mode 100644 index 000000000..38ad5cd5e --- /dev/null +++ b/srsepc/CMakeLists.txt @@ -0,0 +1,50 @@ +# +# Copyright 2013-2017 Software Radio Systems Limited +# +# This file is part of srsLTE +# +# srsLTE is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# srsLTE is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# A copy of the GNU Affero General Public License can be found in +# the LICENSE file in the top-level directory of this distribution +# and at http://www.gnu.org/licenses/. +# + +find_package(LibConfig REQUIRED) +find_package(SCTP REQUIRED) + +if(BUILD_STATIC) + set(LIBCONFIGPP_LIBRARIES "${LIBCONFIGPP_STATIC_LIBRARY_PATH}") +endif(BUILD_STATIC) + +if(NOT Boost_FOUND) + message(FATAL_ERROR "Boost required to compile srsEPC") +endif() + +######################################################################## +# Setup the include and linker paths +######################################################################## +include_directories( + ${Boost_INCLUDE_DIRS} + ${SEC_INCLUDE_DIRS} + ${PROJECT_SOURCE_DIR}/srsepc/hdr +) + +link_directories( + ${Boost_LIBRARY_DIRS} + ${SEC_LIBRARY_DIRS} +) + +######################################################################## +# Add subdirectories +######################################################################## +add_subdirectory(src) +add_subdirectory(test) diff --git a/srsepc/docs/.gitignore b/srsepc/docs/.gitignore new file mode 100644 index 000000000..a007feab0 --- /dev/null +++ b/srsepc/docs/.gitignore @@ -0,0 +1 @@ +build/* diff --git a/srsepc/docs/Makefile b/srsepc/docs/Makefile new file mode 100644 index 000000000..5dfc21fa8 --- /dev/null +++ b/srsepc/docs/Makefile @@ -0,0 +1,216 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " applehelp to make an Apple Help Book" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" + +.PHONY: clean +clean: + rm -rf $(BUILDDIR)/* + +.PHONY: html +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +.PHONY: dirhtml +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +.PHONY: singlehtml +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +.PHONY: pickle +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +.PHONY: json +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +.PHONY: htmlhelp +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +.PHONY: qthelp +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/srsEPC.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/srsEPC.qhc" + +.PHONY: applehelp +applehelp: + $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp + @echo + @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." + @echo "N.B. You won't be able to view it unless you put it in" \ + "~/Library/Documentation/Help or install it in your application" \ + "bundle." + +.PHONY: devhelp +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/srsEPC" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/srsEPC" + @echo "# devhelp" + +.PHONY: epub +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +.PHONY: latex +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +.PHONY: latexpdf +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +.PHONY: latexpdfja +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +.PHONY: text +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +.PHONY: man +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +.PHONY: texinfo +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +.PHONY: info +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +.PHONY: gettext +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +.PHONY: changes +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +.PHONY: linkcheck +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +.PHONY: doctest +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +.PHONY: coverage +coverage: + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage + @echo "Testing of coverage in the sources finished, look at the " \ + "results in $(BUILDDIR)/coverage/python.txt." + +.PHONY: xml +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +.PHONY: pseudoxml +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/srsepc/docs/README b/srsepc/docs/README new file mode 100644 index 000000000..7fc58da70 --- /dev/null +++ b/srsepc/docs/README @@ -0,0 +1,7 @@ +# srsepc-docs +The docs of srsEPC require sphinx, and the sphinx-seqdiag and sphinx-blockdiag extensions. + +On Ubuntu, you can do: +sudo apt install python-sphinx python-sphinxcontrib.seqdiag python-sphinxcontrib.blockdiag + +To make the documentation do 'make html' on the main ./docs folder diff --git a/srsepc/docs/source/_imgs/epc-auth-plane.svg b/srsepc/docs/source/_imgs/epc-auth-plane.svg new file mode 100644 index 000000000..af6426710 --- /dev/null +++ b/srsepc/docs/source/_imgs/epc-auth-plane.svg @@ -0,0 +1,289 @@ + + + + + + + + + + image/svg+xml + + + + + + + MME + S6a + + HSS + + + + Diameter + + SCTP + + IP + + L2/L1 + + + + + + + Diameter + + SCTP + + IP + + L2/L1 + + + + + diff --git a/srsepc/docs/source/_imgs/epc-control-plane.svg b/srsepc/docs/source/_imgs/epc-control-plane.svg new file mode 100644 index 000000000..3e84c8a6c --- /dev/null +++ b/srsepc/docs/source/_imgs/epc-control-plane.svg @@ -0,0 +1,598 @@ + + + + + + + + + + image/svg+xml + + + + + + + S1-MME + + + S1-APP + + SCTP + + IP + + L2/L1 + + + + S1-APP + + SCTP + + IP + + L2/L1 + + + + eNB + MME + S11 + + + GTP-C + + UDP + + IP + + L2/L1 + + + S-GW + + + + GTP-C + + UDP + + IP + + L2/L1 + + S5/S8 + + + GTP-C + + UDP + + IP + + L2/L1 + + + P-GW + + + + diff --git a/srsepc/docs/source/_imgs/epc-overall.svg b/srsepc/docs/source/_imgs/epc-overall.svg new file mode 100644 index 000000000..68f037fe7 --- /dev/null +++ b/srsepc/docs/source/_imgs/epc-overall.svg @@ -0,0 +1,381 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + LTE + + + + + + + + HSS + + + + P-GW + + + + MME + + + eNB + + + UE + + + + + + + S5/S8 + S1-U + S1-MME + + S6a + S11 + + diff --git a/srsepc/docs/source/_imgs/epc-user-plane.svg b/srsepc/docs/source/_imgs/epc-user-plane.svg new file mode 100644 index 000000000..23d4519ef --- /dev/null +++ b/srsepc/docs/source/_imgs/epc-user-plane.svg @@ -0,0 +1,388 @@ + + + + + + + + + + image/svg+xml + + + + + + + S1-U + + + GTP-U + + UDP + + IP + + L2/L1 + + + + GTP-U + + UDP + + IP + + L2/L1 + + + + eNB + S-GW + S5/S8 + + + GTP-U + + UDP + + IP + + L2/L1 + + + P-GW + + + diff --git a/srsepc/docs/source/_static/.gitignore b/srsepc/docs/source/_static/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/srsepc/docs/source/_templates/.gitignore b/srsepc/docs/source/_templates/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/srsepc/docs/source/conf.py b/srsepc/docs/source/conf.py new file mode 100644 index 000000000..1855f653f --- /dev/null +++ b/srsepc/docs/source/conf.py @@ -0,0 +1,283 @@ +# -*- coding: utf-8 -*- +# +# srsEPC documentation build configuration file, created by +# sphinx-quickstart on Mon Oct 2 14:30:47 2017. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = ['sphinxcontrib.seqdiag','sphinxcontrib.blockdiag'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'srsEPC' +copyright = u'2017, Pedro Alvarez' +author = u'Pedro Alvarez' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = u'2.0.0' +# The full version, including alpha/beta/rc tags. +release = u'2.0.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = [] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'alabaster' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +html_theme_options = {"nosidebar": "true"} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (relative to this directory) to use as a favicon of +# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' +#html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# Now only 'ja' uses this config value +#html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +#html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'srsEPCdoc' + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', + +# Latex figure (float) alignment +#'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'srsEPC.tex', u'srsEPC Documentation', + u'Pedro Alvarez', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'srsepc', u'srsEPC Documentation', + [author], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'srsEPC', u'srsEPC Documentation', + author, 'srsEPC', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False diff --git a/srsepc/docs/source/epc_design.rst b/srsepc/docs/source/epc_design.rst new file mode 100644 index 000000000..eabc36437 --- /dev/null +++ b/srsepc/docs/source/epc_design.rst @@ -0,0 +1,50 @@ +EPC Design +========== + +Code Structure +************** +.. blockdiag:: + +The LTE library should include the following functionality that will be common accress multiple nodes. + + blockdiag { + srsLTE -> lib -> src -> upper -> gtpu.cc; + upper -> gtpc.cc; + upper -> s1app.cc; + upper -> diameter.cc; + src -> asn1; + } + + +The examples should aim to include the following classes + +.. blockdiag:: + + blockdiag { + srsLTE -> srsepc -> src -> mme -> mme.cc; + src -> hss -> hss.cc; + src -> spgw -> spgw.cc; + srsepc -> examples -> srsepc.cc; + examples -> srsmme.cc; + examples -> srshss.cc; + examples -> srsspgw.cc; + } + + +MME Design +********** + +The srsMME must maintain three EPC interfaces, the S1-MME, the S11 and the S6a interfaces. The S1-MME will use SCTP (one-to-many or one-to-one) sockets and the S11 will use the GTP-Cv2 protocol over UDP. The S6a will be implmented as a Diameter application over UDP. + +The main loop of this + +In a future, multi-threading scenario, + +HSS Design +********** + +S-GW Design +*********** + +P-GW Design +*********** diff --git a/srsepc/docs/source/epc_overview.rst b/srsepc/docs/source/epc_overview.rst new file mode 100644 index 000000000..40309eee5 --- /dev/null +++ b/srsepc/docs/source/epc_overview.rst @@ -0,0 +1,225 @@ +EPC Overview +============ + +The Evolved Packet Core (EPC) refers to the elements of an LTE network that make up the core of the network. The main functionality of these elements is to provide data conectivity, mobility and user authentification. + +:ref:`epc-overall` illustrates the main components and their interfaces in the EPC. + +.. _epc-overall: + +.. figure:: _imgs/epc-overall.svg + + EPC overall architecture + +* *HSS*: The Home Subscriber Service (HSS) is the user database. It stores information such as the user's id, key, usage limits, etc. It is responsible for authenticating an authorizing the user's access to the network. + +* *MME*: Mobility Managment Entity (MME) is the main control element in the network. It handles mobility and attach control messages. It is also responsible for paging UEs in idle mode. + +* *S-GW*: The S-GW is the main dataplane gateway for the users, as it provides the mobility anchor for the UEs. It works as an IP router and helps setting up GTP sessions between the eNB and the P-GW. + +* *P-GW*: The Packet Gateway (P-GW) is the point of contact with external networks. It enforces the QoS parameters for subscriber sessions. + +EPC User and Control Plane +************************** + +In this subsection, we will breifly describe the EPC's user and control plane. The user plane, uses the GPRS Tunneling Protocol to estabilish tunnels between the P-GW and the eNB. The GTP is a IP-over-IP protocol, that encapsulates user packets in another IP packet plus a label to provide mobility. To see a more detailed description of GTP, go to :ref:`gtp-section`. + +These user plane tunnels are set up between the eNB, the S-GW and the P-GW over the S1-U and S5/S8 interfaces. The full protocol stack is illustrated in :ref:`epc-user-plane`. + +.. _epc-user-plane: + +.. figure:: _imgs/epc-user-plane.svg + + EPC User Plane (S1-U and S5/S8) + +To establish these user tunnels, the GTP-Cv2 protocol and the S1-APP protocol are used. These protocols provide the interfaces between the eNB, the MME, the S-PGW and the P-GW. The full protocol stack can be seen in :ref:`epc-control-plane`. The details of the GTP-Cv2 and S1-APP can be seen in :ref:`gtp-section` and :ref:`s1app-section`, respectively. + +.. _epc-control-plane: + +.. figure:: _imgs/epc-control-plane.svg + + EPC Control Plane (S1-MME, S11 and S5/S8) + +Finally, to authenticate the user and authorize him or her, the MME comunicates with the HSS over the S6a interface. This interface will run the Diameter protocol the exchange user authentification and authorization information, as seen in :ref:`epc-auth-plane`. More details on :ref:`diameter-section` + +.. _epc-auth-plane: + +.. figure:: _imgs/epc-auth-plane.svg + + EPC Authentication Plane (S6a) + +Procedures +********** + +In this section we will generally describe the most relevant procedures and their implementation status. This will be more of an higher layer view, as the details of each message passed will be elaborated on the :ref:`s1app-section`, :ref:`gtp-section` and :ref:`diameter-section` sections. + +UE Attach proceedure +++++++++++++++++++++ + +The UE attach procedure is one of the first and most crucial steps for the UE to get connectivity. For this reason, this is the first procedure to be described. This can be broken down to multiple procedures and you can see bellow + +.. seqdiag:: + + seqdiag { + + === Random Access Procedure === + UE <- eNB [label = "MIB"] + UE <- eNB [label = "SIB1"] + UE <- eNB [label = "SIB2"] + UE -> eNB [label = "Random Access Preamble"]; + UE <- eNB [label = "Random Access Response [Tmp C-RNTI]"]; + UE -> eNB [label = "RRC Connection Request [Tmp C-RNTI]"]; + UE <- eNB [label = "RRC Connection Setup [C-RNTI]"]; + UE -> eNB [label = "RRC Connection Completed [Attach Request (IMSI), PDN Connection Request]"]; + === User Authentication Procedure === + eNB -> MME [label = "Initial UE Msg [Attach Request, PDN Connection Request]"]; + MME -> HSS [label = "Auth Info Request (IMSI)"]; + MME <- HSS [label = "Auth Info Answer (Kasme, AUTN, RAND, XRES)"] + eNB <- MME [label = "DL NAS Xport [Authn Request]"]; + UE <- eNB [label = "DL Info Xfer [Auth Request (AUTN, RAND)]"]; + UE -> eNB [label = "Auth Response (RES)"]; + eNB -> MME [label = "Auth Response (RES)", note = "MME compares RES with XRES"]; + === NAS Security Setup Procedure === + eNB <- MME [label = "DL NAS Xport [Security Mode Command]"]; + UE <- eNB [label = "DL Info Xfer [Security Mode Command]"]; + UE -> eNB [label = "Security Mode Complete"] + eNB -> MME [label = "SMC Completed"] + === Authorization === + MME -> HSS [label = "Location Update Request (IMSI)"] + MME <- HSS [label = "Location Update Response (Subscription Data)"] + === GTP Tunnel setup === + MME -> SGW [label = "Create Session Request (IMSI, TEID, PGW IP)"] + SGW -> PGW [label = "Create Session Request (IMSI, TEID)"] + SGW <- PGW [label = "Create Session Response (TEIDs)", note = "S5 GTP Tunnel created"] + MME <- SGW [label = "Create Session Response (TEIDs)"] + eNB <- MME [label = "Initial Context Setup Request (UE Context Info, TEID)", note="NAS Attach Accept, NAS Activate default bearer"] + UE <- eNB [label = "RRC Security Mode Command (AS Algorithm)"] + UE -> eNB [label = "RRC Security Mode Complete"] + //UE <-> eNB [label = "UE Radio Capabilities"] + UE <- eNB [label = "RRC Connection Reconfiguration", note = "NAS Attach Accept, NAS Activate Default Bearer"] + UE -> eNB [label = "RRC Reconfiguration Complete"] + eNB -> MME [label = "Initial Context Setup Complete (S1U TIED)"] + UE -> eNB [label = "Uplink Information Transfer [NAS Attach Complete, NAS Activate default bearer accept]"] + eNB -> MME [label = "Uplink NAS Xport [NAS Attach Complete, NAS Activate default bearer accept]"] + MME -> SGW [label = "Modify bearer request (S1-U TEID)"] + MME <- SGW [label = "Modify bearer response"] + === Networking Setup === + } + +.. _gtp-section: + +GPRS Tunneling Protocol +*********************** + +The GPRS Tunneling Protocol (GTP) main objective is to tunnel IP packets to the UE, allowing him to keep his IP even when the user is mobile. +It is composed of two parts, the user plane and the control plane. + +Transport Layer ++++++++++++++++ + +Both GTP-C and GTP-U use UDP for the transport layer. The specific port for GTP-C TX and RX is 2123. For GTP-U packets must have a destination port of 2152, but can use any source port. + +Setting up TEIDs +++++++++++++++++ + +In this section we will describe the setup of GTP tunnels, both between the S-GW and P-GW and between the S-GW and the eNB. +We will start with the setup of the of GTP tunnels between the S-GW and the P-GW for simplicity. + +Initially, the S-GW sends a message to TEID 0 (the butler tunnel) saying that it wants to set up a GTP-U tunnel. This should include the IMSI of the user, the IP address of the S-GW, control plane TEID_sgw_d, user plane TEID_sgw_d, + +The P-GW replies with the with the Create Session Response message, that contains the control TEID_pgw_u that the P-GW allocated for signaling messages for that UE. It will also send the P-GWs IP address and user TEID_pgw_u for uplink user traffic. After this, the TEID tunnels are set up between the S-GW and the P-GW. + +For the set up of GTP-U tunnels between the eNB and the S-GW the process is similar, but the S1-MME (which uses S1-APP instead of GTP-C) must be used. This procedure is initiated by the MME requesting a GTP-U tunnel on behalf of the eNB, by sending a Create Session Request to the S-GW. The S-GW will create a tunnel between himself and the P-GW and after that it will reply to the MME. The MME will finally relay the information of the IP of the S-GW and the TEIDs to the eNB in the Initial Context Setup Request message. + +The whole process is illustrated below: + +.. seqdiag:: + + seqdiag { + activation = none; + MME -> S-GW [label = "Create Session Request"]; + S-GW -> P-GW [label = "Create Session Request"] + S-GW <- P-GW [label = "Create Session Response"]; + MME <- S-GW [label = "Create Session Response"]; + eNB <- MME [label = "Initial Context Setup"]; + } + + + +.. _s1app-section: + +S1-APP +****** + +In this section, we will describe the S1-APP protocol. The S1-APP will run over SCTP and the eNB will initiate the assotiation using the destination port 36412. + +This protocol involved in of multiple procedures, such as S1-MME Setup, UE attach, paging etc. +As this protocol is quite large, we will focus on the procedures we consider most relevant. + +The following sub-sections describe these procedures and give some small indication of their implementation status: + +* :ref:`s1-setup` +* :ref:`erab-setup-request` + +.. _s1-setup: + +S1 Setup +++++++++++ + +This is the first procedure between the eNB and the MME, started once the transport layer is active, to setup the S1-MME connection. +After this procedure takes place, both nodes will store the information exchanged. If the information is already present, it is erased and updated with the most recent information exchanged. + +In this procedure, the following information is sent to the MME from the eNB: + +* *eNB Id* (M): This field will be the global eNB Id; +* *eNB Name* (O): This field will include the human readable name of the eNB; +* *Supported TA* (M): This field will include the +* *Default Paging DRX* (M): This message +* *CSG List Ids* (O): This + +In the case of success, the MME will reply the following: + +* *MME Name* (O): This message will include the human readable name of the MME; +* *Served GUMMEI* (M): This field will contain the Globally Unique MME Id. This is composed by the MCC, MNC, MME Group Id and MME code. +* *Relative MME Capacity* (M): This message will contain a weight factor for MME load balancing purposes +* *Criticality Diagnosis* (O): This field indicates if some IE were not understood by the MME or missing + +In the case of failure, the MME will reply the following: + +* *Cause Id* (M): This message will what was the cause for the setup failure; +* *Time to wait* (O): This will indicate the eNB to wait at least the indicated amount of time before restarting the S1 Setup +* *Criticality Diagnosis* (O): This field indicates if some IE were not understood by the MME or missing + +You can see the message diagram for both the success and failure case below: + +.. _success-s1-setup: + +.. seqdiag:: + + seqdiag { + activation = none; + eNB -> MME [label = "S1 Setup Request"]; + eNB <- MME [label = "S1 Setup Response"]; + } + +.. _fail-s1-setup: + +.. seqdiag:: + + seqdiag { + activation = none; + eNB -> MME [label = "S1 Setup Request"] + eNB <- MME [label = "S1 Setup Failure"] + } + + +.. _erab-setup-request: + +E-RAB Setup Request ++++++++++++++++++++ + +.. _diameter-section: + +Diameter +******** + diff --git a/srsepc/docs/source/epc_usage.rst b/srsepc/docs/source/epc_usage.rst new file mode 100644 index 000000000..e98ac2cfa --- /dev/null +++ b/srsepc/docs/source/epc_usage.rst @@ -0,0 +1,2 @@ +EPC Usage +********* diff --git a/srsepc/docs/source/index.rst b/srsepc/docs/source/index.rst new file mode 100644 index 000000000..4cacb24ed --- /dev/null +++ b/srsepc/docs/source/index.rst @@ -0,0 +1,18 @@ + +.. srsEPC documentation master file, created by + sphinx-quickstart on Mon Oct 2 14:30:47 2017. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to srsEPC's documentation! +================================== + + +.. toctree:: + :maxdepth: 2 + + epc_overview.rst + epc_design.rst + epc_usage.rst + + From 3e5e2444400fc0582a3500b3d9f41ed9ec886f43 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 9 Oct 2017 12:22:17 +0100 Subject: [PATCH 002/172] Changing CMakeLists to compile EPC --- CMakeLists.txt | 11 +++++++++-- srsepc/CMakeLists.txt | 2 +- srsepc/hdr/mme/mme.h | 40 ++++++++++++++++++++++++++++++++++++++++ srsepc/src/mme/mme.cc | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 srsepc/hdr/mme/mme.h create mode 100644 srsepc/src/mme/mme.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index d72bb5fef..4bbd96c1c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,6 +60,7 @@ set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "") ######################################################################## option(ENABLE_SRSUE "Build srsUE application" ON) option(ENABLE_SRSENB "Build srsENB application" ON) +option(ENABLE_SRSEPC "Build srsEPC application" ON) option(ENABLE_VOLK "Enable use of VOLK SIMD library" ON) option(ENABLE_GUI "Enable GUI (using srsGUI)" ON) @@ -155,7 +156,7 @@ else(BLADERF_FOUND OR UHD_FOUND OR SOAPYSDR_FOUND) endif(BLADERF_FOUND OR UHD_FOUND OR SOAPYSDR_FOUND) # Boost -if(ENABLE_SRSUE OR ENABLE_SRSENB) +if(ENABLE_SRSUE OR ENABLE_SRSENB OR ENABLE_SRSEPC) if(BUILD_STATIC) set(Boost_USE_STATIC_LIBS ON) endif(BUILD_STATIC) @@ -177,7 +178,7 @@ if(ENABLE_SRSUE OR ENABLE_SRSENB) "1.65.0" "1.65" "1.66.0" "1.66" "1.67.0" "1.67" "1.68.0" "1.68" "1.69.0" "1.69" ) find_package(Boost "1.35" COMPONENTS ${BOOST_REQUIRED_COMPONENTS}) -endif(ENABLE_SRSUE OR ENABLE_SRSENB) +endif(ENABLE_SRSUE OR ENABLE_SRSENB OR ENABLE_SRSEPC) # srsGUI if(ENABLE_GUI) @@ -371,3 +372,9 @@ if(RF_FOUND) else(RF_FOUND) message(STATUS "srsUE and srsENB builds disabled due to missing RF driver") endif(RF_FOUND) +if(ENABLE_SRSENB) + message(STATUS "Building with srsEPC") + add_subdirectory(srsepc) +else(ENABLE_SRSEPC) + message(STATUS "srsEPC build disabled") +endif(ENABLE_SRSUE) diff --git a/srsepc/CMakeLists.txt b/srsepc/CMakeLists.txt index 38ad5cd5e..0006e5191 100644 --- a/srsepc/CMakeLists.txt +++ b/srsepc/CMakeLists.txt @@ -47,4 +47,4 @@ link_directories( # Add subdirectories ######################################################################## add_subdirectory(src) -add_subdirectory(test) +#add_subdirectory(test) diff --git a/srsepc/hdr/mme/mme.h b/srsepc/hdr/mme/mme.h new file mode 100644 index 000000000..14f7c686c --- /dev/null +++ b/srsepc/hdr/mme/mme.h @@ -0,0 +1,40 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "srslte/common/log.h" + +#ifndef MME_H +#define MME_H + +namespace srsepc{ + +class mme +{ + +}; + +} // namespace srsepc +#endif // MME_H diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc new file mode 100644 index 000000000..44a81569f --- /dev/null +++ b/srsepc/src/mme/mme.cc @@ -0,0 +1,33 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + + +#include "mme.h" + +class srsmme +{ + int tst; +}; From 5c0e2ee32eac1c4a7dc3dd47c96759c4761f79c7 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 9 Oct 2017 14:11:43 +0100 Subject: [PATCH 003/172] Starting to add CMake support --- CMakeLists.txt | 5 +++-- srsepc/hdr/CMakeLists.txt | 5 +++++ srsepc/src/CMakeLists.txt | 42 +++++++++++++++++++++++++++++++++++ srsepc/src/main.cc | 7 ++++++ srsepc/src/mme/CMakeLists.txt | 24 ++++++++++++++++++++ 5 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 srsepc/hdr/CMakeLists.txt create mode 100644 srsepc/src/CMakeLists.txt create mode 100644 srsepc/src/main.cc create mode 100644 srsepc/src/mme/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 4bbd96c1c..232445013 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -372,9 +372,10 @@ if(RF_FOUND) else(RF_FOUND) message(STATUS "srsUE and srsENB builds disabled due to missing RF driver") endif(RF_FOUND) -if(ENABLE_SRSENB) + +if(ENABLE_SRSEPC) message(STATUS "Building with srsEPC") add_subdirectory(srsepc) else(ENABLE_SRSEPC) message(STATUS "srsEPC build disabled") -endif(ENABLE_SRSUE) +endif(ENABLE_SRSEPC) diff --git a/srsepc/hdr/CMakeLists.txt b/srsepc/hdr/CMakeLists.txt new file mode 100644 index 000000000..093086b96 --- /dev/null +++ b/srsepc/hdr/CMakeLists.txt @@ -0,0 +1,5 @@ +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/version.h.in + ${PROJECT_BINARY_DIR}/version.h +) + diff --git a/srsepc/src/CMakeLists.txt b/srsepc/src/CMakeLists.txt new file mode 100644 index 000000000..28f94aa98 --- /dev/null +++ b/srsepc/src/CMakeLists.txt @@ -0,0 +1,42 @@ + +add_subdirectory(mme) + +# Link libstdc++ and libgcc +if(BUILD_STATIC) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++ -static-libgcc") +endif(BUILD_STATIC) + + +if (RPATH) + SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) +endif (RPATH) + + +add_executable(srsepc main.cc ) +target_link_libraries(srsepc srsenb_upper + srslte_common + srslte_phy + srslte_upper + ${CMAKE_THREAD_LIBS_INIT} + ${Boost_LIBRARIES} + ${SEC_LIBRARIES} + ${LIBCONFIGPP_LIBRARIES} + ${SCTP_LIBRARIES}) + +if (RPATH) + set_target_properties(srsenb PROPERTIES INSTALL_RPATH ".") +endif (RPATH) + +install(TARGETS srsepc DESTINATION ${RUNTIME_DIR}) + +######################################################################## +# Option to run command after build (useful for remote builds) +######################################################################## +if (NOT ${BUILDENB_CMD} STREQUAL "") + message(STATUS "Added custom post-build-ENB command: ${BUILDENB_CMD}") + add_custom_command(TARGET srsenb POST_BUILD COMMAND ${BUILDENB_CMD}) +else(NOT ${BUILDENB_CMD} STREQUAL "") + message(STATUS "No post-build-ENB command defined") +endif (NOT ${BUILDENB_CMD} STREQUAL "") + +install(TARGETS srsepc DESTINATION ${RUNTIME_DIR}) diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc new file mode 100644 index 000000000..89b0aca3c --- /dev/null +++ b/srsepc/src/main.cc @@ -0,0 +1,7 @@ +#include "mme.h" + +int +main (int argc,char * argv[] ) +{ + return 0; +} diff --git a/srsepc/src/mme/CMakeLists.txt b/srsepc/src/mme/CMakeLists.txt new file mode 100644 index 000000000..cd1958566 --- /dev/null +++ b/srsepc/src/mme/CMakeLists.txt @@ -0,0 +1,24 @@ +# +# Copyright 2013-2017 Software Radio Systems Limited +# +# This file is part of srsLTE +# +# srsLTE is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# srsLTE is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# A copy of the GNU Affero General Public License can be found in +# the LICENSE file in the top-level directory of this distribution +# and at http://www.gnu.org/licenses/. +# + +file(GLOB SOURCES "*.cc") +add_library(srsepc_mme STATIC ${SOURCES}) +install(TARGETS srsepc_mme DESTINATION ${LIBRARY_DIR}) + From b561dfa087b92d9afd53fee2351a0189569f9b58 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 9 Oct 2017 15:42:13 +0100 Subject: [PATCH 004/172] Initial skeleton of the code. --- srsepc/hdr/mme/mme.h | 12 +++++++++++- srsepc/src/CMakeLists.txt | 15 ++++++--------- srsepc/src/main.cc | 2 +- srsepc/src/mme/mme.cc | 11 +++++++---- 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/srsepc/hdr/mme/mme.h b/srsepc/hdr/mme/mme.h index 14f7c686c..b7a74a940 100644 --- a/srsepc/hdr/mme/mme.h +++ b/srsepc/hdr/mme/mme.h @@ -24,7 +24,11 @@ * */ -#include "srslte/common/log.h" +/****************************************************************************** + * File: mme.h + * Description: Top-level MME class. Creates and links all + * interfaces and helpers. + *****************************************************************************/ #ifndef MME_H #define MME_H @@ -33,8 +37,14 @@ namespace srsepc{ class mme { +private: + + static mme *instance; + mme(); + virtual ~mme(); }; } // namespace srsepc + #endif // MME_H diff --git a/srsepc/src/CMakeLists.txt b/srsepc/src/CMakeLists.txt index 28f94aa98..47d125a32 100644 --- a/srsepc/src/CMakeLists.txt +++ b/srsepc/src/CMakeLists.txt @@ -13,10 +13,7 @@ endif (RPATH) add_executable(srsepc main.cc ) -target_link_libraries(srsepc srsenb_upper - srslte_common - srslte_phy - srslte_upper +target_link_libraries(srsepc srsepc_mme ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${SEC_LIBRARIES} @@ -32,11 +29,11 @@ install(TARGETS srsepc DESTINATION ${RUNTIME_DIR}) ######################################################################## # Option to run command after build (useful for remote builds) ######################################################################## -if (NOT ${BUILDENB_CMD} STREQUAL "") - message(STATUS "Added custom post-build-ENB command: ${BUILDENB_CMD}") +if (NOT ${BUILDEPC_CMD} STREQUAL "") + message(STATUS "Added custom post-build-EPC command: ${BUILDENB_CMD}") add_custom_command(TARGET srsenb POST_BUILD COMMAND ${BUILDENB_CMD}) -else(NOT ${BUILDENB_CMD} STREQUAL "") - message(STATUS "No post-build-ENB command defined") -endif (NOT ${BUILDENB_CMD} STREQUAL "") +else(NOT ${BUILDEPC_CMD} STREQUAL "") + message(STATUS "No post-build-EPC command defined") +endif (NOT ${BUILDEPC_CMD} STREQUAL "") install(TARGETS srsepc DESTINATION ${RUNTIME_DIR}) diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index 89b0aca3c..954c7cb63 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -1,4 +1,4 @@ -#include "mme.h" +#include "mme/mme.h" int main (int argc,char * argv[] ) diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index 44a81569f..6b6cdb953 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -25,9 +25,12 @@ */ -#include "mme.h" +#include "mme/mme.h" -class srsmme +namespace srsepc{ + +mme::mme() { - int tst; -}; +} + +} //namespace srsepc From b0aaa316c440855cc38c5a170f716c57740e2246 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 9 Oct 2017 16:08:06 +0100 Subject: [PATCH 005/172] Sligth change in design docs --- srsepc/docs/source/epc_design.rst | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/srsepc/docs/source/epc_design.rst b/srsepc/docs/source/epc_design.rst index eabc36437..19ce56212 100644 --- a/srsepc/docs/source/epc_design.rst +++ b/srsepc/docs/source/epc_design.rst @@ -3,16 +3,17 @@ EPC Design Code Structure ************** -.. blockdiag:: The LTE library should include the following functionality that will be common accress multiple nodes. +.. blockdiag:: + blockdiag { srsLTE -> lib -> src -> upper -> gtpu.cc; upper -> gtpc.cc; upper -> s1app.cc; upper -> diameter.cc; - src -> asn1; + src -> asn1; } @@ -22,23 +23,22 @@ The examples should aim to include the following classes blockdiag { srsLTE -> srsepc -> src -> mme -> mme.cc; + mme -> main.cc; src -> hss -> hss.cc; + hss -> main.cc; src -> spgw -> spgw.cc; - srsepc -> examples -> srsepc.cc; - examples -> srsmme.cc; - examples -> srshss.cc; - examples -> srsspgw.cc; + spgw -> main.cc; + srsepc -> src -> main.cc; + src -> epc.cc; } MME Design ********** -The srsMME must maintain three EPC interfaces, the S1-MME, the S11 and the S6a interfaces. The S1-MME will use SCTP (one-to-many or one-to-one) sockets and the S11 will use the GTP-Cv2 protocol over UDP. The S6a will be implmented as a Diameter application over UDP. +The srsMME must maintain three EPC interfaces, the S1-MME, the S11 and the S6a interfaces. The S1-MME will use an SCTP (many-to-one) socket and the S11 will use the GTP-Cv2 protocol over UDP. The S6a will be implmented as a Diameter application over UDP. -The main loop of this - -In a future, multi-threading scenario, +The main loop of the MME will HSS Design ********** From 136e3a26972fefe09b7c968d243c5cb428414824 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 9 Oct 2017 16:49:43 +0100 Subject: [PATCH 006/172] Added some boieler plate code for the MME (contruct, singleton, destruct). --- srsepc/docs/source/epc_design.rst | 2 +- srsepc/hdr/mme/mme.h | 7 +++++++ srsepc/src/mme/mme.cc | 27 ++++++++++++++++++++++++++- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/srsepc/docs/source/epc_design.rst b/srsepc/docs/source/epc_design.rst index 19ce56212..3a1280c99 100644 --- a/srsepc/docs/source/epc_design.rst +++ b/srsepc/docs/source/epc_design.rst @@ -38,7 +38,7 @@ MME Design The srsMME must maintain three EPC interfaces, the S1-MME, the S11 and the S6a interfaces. The S1-MME will use an SCTP (many-to-one) socket and the S11 will use the GTP-Cv2 protocol over UDP. The S6a will be implmented as a Diameter application over UDP. -The main loop of the MME will +The main loop of the MME will HSS Design ********** diff --git a/srsepc/hdr/mme/mme.h b/srsepc/hdr/mme/mme.h index b7a74a940..805607e56 100644 --- a/srsepc/hdr/mme/mme.h +++ b/srsepc/hdr/mme/mme.h @@ -33,10 +33,17 @@ #ifndef MME_H #define MME_H +#include + namespace srsepc{ class mme { +public: + mme* get_instance(void); + + void cleanup(void); + private: static mme *instance; diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index 6b6cdb953..ff24dbe02 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -24,13 +24,38 @@ * */ - +#include #include "mme/mme.h" namespace srsepc{ +mme* mme::instance = NULL; +boost::mutex mme_instance_mutex; + + +mme* +mme::get_instance(void) +{ + boost::mutex::scoped_lock lock(mme_instance_mutex); + if(NULL == instance) { + instance = new mme(); + } + return(instance); +} + mme::mme() { } +void +mme::cleanup(void) +{ + boost::mutex::scoped_lock lock(mme_instance_mutex); + if(NULL != instance) { + delete instance; + instance = NULL; + } +} + + } //namespace srsepc From 429c32cd5a470c82af6c97968d82a60085d1f748 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 9 Oct 2017 18:36:40 +0100 Subject: [PATCH 007/172] Added initial app to run MME. Starting to add S1APP class. --- srsepc/hdr/mme/mme.h | 4 ++-- srsepc/hdr/mme/s1ap.h | 33 +++++++++++++++++++++++++++++++++ srsepc/src/main.cc | 36 ++++++++++++++++++++++++++++++++++++ srsepc/src/mme/mme.cc | 13 +++++++++---- srsepc/src/mme/s1ap.cc | 33 +++++++++++++++++++++++++++++++++ 5 files changed, 113 insertions(+), 6 deletions(-) create mode 100644 srsepc/hdr/mme/s1ap.h create mode 100644 srsepc/src/mme/s1ap.cc diff --git a/srsepc/hdr/mme/mme.h b/srsepc/hdr/mme/mme.h index 805607e56..d46dfdd40 100644 --- a/srsepc/hdr/mme/mme.h +++ b/srsepc/hdr/mme/mme.h @@ -40,9 +40,9 @@ namespace srsepc{ class mme { public: - mme* get_instance(void); + static mme* get_instance(void); - void cleanup(void); + static void cleanup(void); private: diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h new file mode 100644 index 000000000..de1cf9b43 --- /dev/null +++ b/srsepc/hdr/mme/s1ap.h @@ -0,0 +1,33 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +class s1ap +{ +public: + s1ap(); + virtual ~s1ap(); + int enb_listen(); +} diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index 954c7cb63..f77a1cc18 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -1,7 +1,43 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsUE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsUE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ +#include +#include #include "mme/mme.h" + +using namespace std; +using namespace srsepc; +namespace bpo = boost::program_options; + int main (int argc,char * argv[] ) { + //signal(SIGINT, sig_int_handler); + mme *mme = mme::get_instance(); + + cout << "--- Software Radio Systems EPC MME ---" << endl << endl; return 0; } diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index ff24dbe02..e5c4d6e9f 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -32,6 +32,15 @@ namespace srsepc{ mme* mme::instance = NULL; boost::mutex mme_instance_mutex; +mme::mme() +{ + return; +} + +mme::~mme() +{ + return; +} mme* mme::get_instance(void) @@ -43,10 +52,6 @@ mme::get_instance(void) return(instance); } -mme::mme() -{ -} - void mme::cleanup(void) { diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc new file mode 100644 index 000000000..37e71b834 --- /dev/null +++ b/srsepc/src/mme/s1ap.cc @@ -0,0 +1,33 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +namespace srsepc{ + +s1ap::s1ap() +{ +} + +}//namespace srsepc From 58b5831009a698b8e9bf99be616efe73c1fe0d9d Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 9 Oct 2017 19:35:00 +0100 Subject: [PATCH 008/172] Starting to create SCTP socket for S1APP --- srsepc/hdr/mme/s1ap.h | 6 +++++- srsepc/src/mme/s1ap.cc | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index de1cf9b43..2e93db2d4 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -24,10 +24,14 @@ * */ +namespace srsepc{ + class s1ap { public: s1ap(); virtual ~s1ap(); int enb_listen(); -} +}; + +} //namespace srsepc diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 37e71b834..514060178 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -24,10 +24,48 @@ * */ +#include //TODO Remove + +#include +#include +#include +#include +#include +#include "mme/s1ap.h" + namespace srsepc{ s1ap::s1ap() { } +s1ap::~s1ap() +{ +} + +int +s1ap::enb_listen() +{ + /*This function sets up the SCTP socket for eNBs to connect to*/ + int sock_fd; + struct sockaddr_in s1mme_addr;//TODO make this a configurable class memeber. + + sock_fd = socket (AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); + if (sock_fd == -1){ + std::cout << "[S1APP] Could not create SCTP socket" < Date: Tue, 10 Oct 2017 11:51:49 +0100 Subject: [PATCH 009/172] Start of skeleton of MME config file --- srsepc/conf/epc.conf | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 srsepc/conf/epc.conf diff --git a/srsepc/conf/epc.conf b/srsepc/conf/epc.conf new file mode 100644 index 000000000..1bc5d7648 --- /dev/null +++ b/srsepc/conf/epc.conf @@ -0,0 +1,23 @@ +##################################################################### +# srsEPC configuration file +##################################################################### + +##################################################################### +# MME configuration +# +# mme_code: 8-bit MME code identifies the MME within a group. +# mme_group: 16-bit MME group identifier. +# tac: 16-bit Tracking Area Code. +# mcc: Mobile Country Code +# mnc: Mobile Network Code +# mme_bindx_addr: IP subnet to listen for eNB S1 connnections +# +##################################################################### +[mme] +mme_code = 0x19 +mme_group = 0x0001 +phy_cell_id = 1 +tac = 0x0001 +mcc = 208 +mnc = 93 +mme_bindx_addr = 127.0.0.0/24 From 396335afeedf6e659d6715ccda341690ec03dfc9 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 10 Oct 2017 17:32:34 +0100 Subject: [PATCH 010/172] Added initial mechanisms to receive msgs from eNB. --- srsepc/hdr/mme/mme.h | 16 ++++++- srsepc/hdr/mme/s1ap.h | 27 ++++++++++++ srsepc/src/main.cc | 97 +++++++++++++++++++++++++++++++++++++++--- srsepc/src/mme/mme.cc | 30 ++++++++++--- srsepc/src/mme/s1ap.cc | 36 ++++++++++++++-- 5 files changed, 186 insertions(+), 20 deletions(-) diff --git a/srsepc/hdr/mme/mme.h b/srsepc/hdr/mme/mme.h index d46dfdd40..d9a985b19 100644 --- a/srsepc/hdr/mme/mme.h +++ b/srsepc/hdr/mme/mme.h @@ -34,22 +34,34 @@ #define MME_H #include +#include "s1ap.h" + namespace srsepc{ +typedef struct{ + s1ap_args_t s1ap_args; +} all_args_t; + + class mme { public: static mme* get_instance(void); static void cleanup(void); + + int init(all_args_t* args); + + int get_s1_mme(); private: - static mme *instance; mme(); virtual ~mme(); - + static mme *m_instance; + s1ap m_s1ap; + }; } // namespace srsepc diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 2e93db2d4..3a50cc80f 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -26,12 +26,39 @@ namespace srsepc{ +const uint16_t S1MME_PORT = 36412; + +typedef struct{ + uint8_t mme_code; + uint16_t mme_group; + uint16_t tac; // 16-bit tac + uint16_t mcc; // BCD-coded with 0xF filler + uint16_t mnc; // BCD-coded with 0xF filler + std::string mme_bindx_addr; + std::string mme_name; +} s1ap_args_t; + class s1ap { public: s1ap(); virtual ~s1ap(); int enb_listen(); + + int init(s1ap_args_t s1ap_args); + + int get_s1_mme(); + +private: + uint8_t m_mme_code; + uint16_t m_mme_group; + uint16_t m_tac; // 16-bit tac + uint16_t m_mcc; // BCD-coded with 0xF filler + uint16_t m_mnc; // BCD-coded with 0xF filler + std::string m_mme_bindx_addr; + std::string m_mme_name; + + int m_s1mme; }; } //namespace srsepc diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index f77a1cc18..48c252da1 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -8,12 +8,12 @@ * * This file is part of srsLTE. * - * srsUE is free software: you can redistribute it and/or modify + * srsLTE is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * - * srsUE is distributed in the hope that it will be useful, + * srsLTE is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. @@ -24,20 +24,103 @@ * */ #include +#include +#include +#include +#include #include #include "mme/mme.h" - using namespace std; using namespace srsepc; namespace bpo = boost::program_options; +bool running = true; + +/* +void +parse_args(all_args_t *args, int argc, char* argv[]) { + + string mme_code; + string mme_group; + string tac; + string mcc; + string mnc; + + // Command line only options + bpo::options_description general("General options"); + general.add_options() + ("help,h", "Produce help message") + ("version,v", "Print version information and exit") + ; + + // Command line or config file options + bpo::options_description common("Configuration options"); + common.add_options() + + ("mme.enb_id", bpo::value(&enb_id)->default_value("0x0"), "eNodeB ID") + ("mme.name", bpo::value(&args->enb.s1ap.enb_name)->default_value("srsenb01"), "eNodeB Name") + ("mme.cell_id", bpo::value(&cell_id)->default_value("0x0"), "Cell ID") + ("mme.tac", bpo::value(&tac)->default_value("0x0"), "Tracking Area Code") + ("mme.mcc", bpo::value(&mcc)->default_value("001"), "Mobile Country Code") + ("mme.mnc", bpo::value(&mnc)->default_value("01"), "Mobile Network Code") + ("mme.mme_bindx_addr", bpo::value(&args->enb.s1ap.mme_addr)->default_value("127.0.0.1"),"IP address of MME for S1 connnection") + ; + + // Positional options - config file location + bpo::options_description position("Positional options"); + position.add_options() + ("config_file", bpo::value< string >(&config_file), "eNodeB configuration file") + ; + bpo::positional_options_description p; + p.add("config_file", -1) + + return; +} +*/ + int main (int argc,char * argv[] ) -{ - //signal(SIGINT, sig_int_handler); - mme *mme = mme::get_instance(); - +{ cout << "--- Software Radio Systems EPC MME ---" << endl << endl; + + //signal(SIGINT, sig_int_handler); + + //TODO these should be passed from config files + all_args_t args; + args.s1ap_args.mme_code = 0x01; + args.s1ap_args.mme_group = 0x0001; + args.s1ap_args.tac = 0x0001; + args.s1ap_args.mcc = 0x01; + args.s1ap_args.mnc = 0x01; + args.s1ap_args.mme_bindx_addr="127.0.0.0/24"; + + struct sockaddr_in enb_addr; + char readbuf[1000]; + struct sctp_sndrcvinfo sri; + socklen_t fromlen; + int rd_sz; + int msg_flags; + + mme *mme = mme::get_instance(); + if (mme->init(&args)) { + cout << "Error initializing MME" << endl; + exit(1); + } + + //Initalize S1-MME scoket + int s1mme = mme->get_s1_mme(); + while(running) + { + cout << "Waiting for SCTP Msg" << endl; + rd_sz = sctp_recvmsg(s1mme, (void*) readbuf, sizeof(readbuf),(struct sockaddr*) &enb_addr, &fromlen, &sri, &msg_flags); + if (rd_sz == -1){ + cout<< "Error reading from SCTP socket"< //TODO Remove #include #include "mme/mme.h" namespace srsepc{ -mme* mme::instance = NULL; +mme* mme::m_instance = NULL; boost::mutex mme_instance_mutex; mme::mme() @@ -46,21 +47,36 @@ mme* mme::get_instance(void) { boost::mutex::scoped_lock lock(mme_instance_mutex); - if(NULL == instance) { - instance = new mme(); + if(NULL == m_instance) { + m_instance = new mme(); } - return(instance); + return(m_instance); } void mme::cleanup(void) { boost::mutex::scoped_lock lock(mme_instance_mutex); - if(NULL != instance) { - delete instance; - instance = NULL; + if(NULL != m_instance) { + delete m_instance; + m_instance = NULL; } } +int +mme::init(all_args_t* args) +{ + if(m_s1ap.init(args->s1ap_args)){ + std::cout << "Error initializing MME S1APP" << std::endl; + exit(-1); + } + return 0; +} + +int +mme::get_s1_mme() +{ + return m_s1ap.get_s1_mme(); +} } //namespace srsepc diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 514060178..b53fe0479 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -43,11 +43,26 @@ s1ap::~s1ap() { } +int +s1ap::init(s1ap_args_t s1ap_args) +{ + m_mme_code = s1ap_args.mme_code ; + m_mme_group = s1ap_args.mme_group; + m_tac = s1ap_args.tac; + m_mcc = s1ap_args.mcc; + m_mnc = s1ap_args.mnc; + m_mme_bindx_addr = s1ap_args.mme_bindx_addr; + m_mme_name = std::string("SRS MME"); + + m_s1mme = enb_listen(); + return 0; +} + int s1ap::enb_listen() { /*This function sets up the SCTP socket for eNBs to connect to*/ - int sock_fd; + int sock_fd, err; struct sockaddr_in s1mme_addr;//TODO make this a configurable class memeber. sock_fd = socket (AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); @@ -59,13 +74,26 @@ s1ap::enb_listen() //S1-MME bind bzero(&s1mme_addr, sizeof(s1mme_addr)); s1mme_addr.sin_family = AF_INET; - s1mme_addr.sin_addr.s_addr = htonl(INADDR_ANY); - s1mme_addr.sin_port = htons(18000); //TODO define S1MME_PORT + s1mme_addr.sin_addr.s_addr = htonl(INADDR_ANY); //TODO this should use the bindx information + s1mme_addr.sin_port = htons(S1MME_PORT); + err = bind(sock_fd, (struct sockaddr*) &s1mme_addr, sizeof (s1mme_addr)); + if (err != 0){ + std::cout << "Error binding SCTP socket" << std::endl; + } //Listen for connections - listen(sock_fd,SOMAXCONN); + err = listen(sock_fd,SOMAXCONN); + if (err != 0){ + std::cout << "Error in SCTP socket listen" << std::endl; + } return sock_fd; } +int +s1ap::get_s1_mme() +{ + return m_s1mme; +} + }//namespace srsepc From f93335fa50898fd2a1b5a27ce75fb7b87cd71daa Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 11 Oct 2017 12:22:02 +0100 Subject: [PATCH 011/172] Fixed bug of not subscribing to sctp_data_io_event --- srsepc/hdr/mme/mme.h | 2 ++ srsepc/hdr/mme/s1ap.h | 4 ++-- srsepc/src/main.cc | 36 +++++++++++++++++++++++++++-------- srsepc/src/mme/mme.cc | 7 +++++++ srsepc/src/mme/s1ap.cc | 43 ++++++++++++++++++++++++++++++++++++------ 5 files changed, 76 insertions(+), 16 deletions(-) diff --git a/srsepc/hdr/mme/mme.h b/srsepc/hdr/mme/mme.h index d9a985b19..7436993da 100644 --- a/srsepc/hdr/mme/mme.h +++ b/srsepc/hdr/mme/mme.h @@ -53,6 +53,8 @@ public: int init(all_args_t* args); + void stop(); + int get_s1_mme(); private: diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 3a50cc80f..27e275736 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -43,9 +43,9 @@ class s1ap public: s1ap(); virtual ~s1ap(); - int enb_listen(); - + int enb_listen(); int init(s1ap_args_t s1ap_args); + void stop(); int get_s1_mme(); diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index 48c252da1..67399f9a2 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -24,6 +24,8 @@ * */ #include +#include +#include #include #include #include @@ -37,6 +39,12 @@ namespace bpo = boost::program_options; bool running = true; +void +sig_int_handler(int signo){ + running = false; +} + + /* void parse_args(all_args_t *args, int argc, char* argv[]) { @@ -84,7 +92,7 @@ main (int argc,char * argv[] ) { cout << "--- Software Radio Systems EPC MME ---" << endl << endl; - //signal(SIGINT, sig_int_handler); + signal(SIGINT, sig_int_handler); //TODO these should be passed from config files all_args_t args; @@ -100,7 +108,7 @@ main (int argc,char * argv[] ) struct sctp_sndrcvinfo sri; socklen_t fromlen; int rd_sz; - int msg_flags; + int msg_flags=0; mme *mme = mme::get_instance(); if (mme->init(&args)) { @@ -110,17 +118,29 @@ main (int argc,char * argv[] ) //Initalize S1-MME scoket int s1mme = mme->get_s1_mme(); + cout << "Socket: " << s1mme; while(running) { - cout << "Waiting for SCTP Msg" << endl; + cout << "Waiting for SCTP Msg on: " << s1mme << endl; + //cout << "Sri:" << sri <stop(); + mme->cleanup(); + cout << "--- exiting ---" << endl; return 0; } diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index e42e4f08a..c898d1a73 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -73,6 +73,13 @@ mme::init(all_args_t* args) return 0; } +void +mme::stop() +{ + m_s1ap.stop(); + return; +} + int mme::get_s1_mme() { diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index b53fe0479..2e6fc0b2b 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -31,11 +31,13 @@ #include #include #include +#include #include "mme/s1ap.h" namespace srsepc{ -s1ap::s1ap() +s1ap::s1ap(): + m_s1mme(-1) { } @@ -58,12 +60,28 @@ s1ap::init(s1ap_args_t s1ap_args) return 0; } +void +s1ap::stop() +{ + if (m_s1mme != -1){ + close(m_s1mme); + } + return; +} + +int +s1ap::get_s1_mme() +{ + return m_s1mme; +} + int s1ap::enb_listen() { /*This function sets up the SCTP socket for eNBs to connect to*/ int sock_fd, err; struct sockaddr_in s1mme_addr;//TODO make this a configurable class memeber. + struct sctp_event_subscribe evnts; sock_fd = socket (AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); if (sock_fd == -1){ @@ -71,6 +89,22 @@ s1ap::enb_listen() return -1; } + //Set timeout + struct timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 0; + if (setsockopt (sock_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0){ + std::cout << "Set socket timeout failed" << std::endl; + return -1; + } + + bzero (&evnts, sizeof (evnts)) ; + evnts.sctp_data_io_event = 1; + if(setsockopt(sock_fd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof (evnts))){ + std::cout << "Subscribing to sctp_data_io_events failed" << std::cout; + return -1; + } + //S1-MME bind bzero(&s1mme_addr, sizeof(s1mme_addr)); s1mme_addr.sin_family = AF_INET; @@ -79,21 +113,18 @@ s1ap::enb_listen() err = bind(sock_fd, (struct sockaddr*) &s1mme_addr, sizeof (s1mme_addr)); if (err != 0){ std::cout << "Error binding SCTP socket" << std::endl; + return -1; } //Listen for connections err = listen(sock_fd,SOMAXCONN); if (err != 0){ std::cout << "Error in SCTP socket listen" << std::endl; + return -1; } return sock_fd; } -int -s1ap::get_s1_mme() -{ - return m_s1mme; -} }//namespace srsepc From 0a670d526af81390016ea021f39611c4119b4c4a Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 11 Oct 2017 16:18:47 +0100 Subject: [PATCH 012/172] Added some logging functionality. --- srsepc/hdr/mme/mme.h | 18 ++++++++++++++++++ srsepc/hdr/mme/s1ap.h | 5 ++++- srsepc/src/CMakeLists.txt | 1 + srsepc/src/main.cc | 1 + srsepc/src/mme/mme.cc | 13 ++++++++++++- srsepc/src/mme/s1ap.cc | 6 +++++- 6 files changed, 41 insertions(+), 3 deletions(-) diff --git a/srsepc/hdr/mme/mme.h b/srsepc/hdr/mme/mme.h index 7436993da..3749eef2f 100644 --- a/srsepc/hdr/mme/mme.h +++ b/srsepc/hdr/mme/mme.h @@ -34,13 +34,24 @@ #define MME_H #include +#include "srslte/common/logger_file.h" +#include "srslte/common/log_filter.h" #include "s1ap.h" namespace srsepc{ + +typedef struct { + std::string s1ap_level; + std::string all_level; + int s1ap_hex_limit; + std::string filename; +}log_args_t; + typedef struct{ s1ap_args_t s1ap_args; + log_args_t log_args; } all_args_t; @@ -63,6 +74,13 @@ private: virtual ~mme(); static mme *m_instance; s1ap m_s1ap; + + /*Logs*/ + srslte::logger_stdout m_logger_stdout; + srslte::logger_file m_logger_file; + srslte::logger *m_logger; + + srslte::log_filter m_s1ap_log; }; diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 27e275736..5a3de3ac6 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -23,6 +23,7 @@ * and at http://www.gnu.org/licenses/. * */ +#include "srslte/common/log.h" namespace srsepc{ @@ -44,7 +45,7 @@ public: s1ap(); virtual ~s1ap(); int enb_listen(); - int init(s1ap_args_t s1ap_args); + int init(s1ap_args_t s1ap_args, srslte::log *s1ap_log); void stop(); int get_s1_mme(); @@ -58,6 +59,8 @@ private: std::string m_mme_bindx_addr; std::string m_mme_name; + srslte::log *m_log_h; + int m_s1mme; }; diff --git a/srsepc/src/CMakeLists.txt b/srsepc/src/CMakeLists.txt index 47d125a32..11985c134 100644 --- a/srsepc/src/CMakeLists.txt +++ b/srsepc/src/CMakeLists.txt @@ -14,6 +14,7 @@ endif (RPATH) add_executable(srsepc main.cc ) target_link_libraries(srsepc srsepc_mme + srslte_common ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${SEC_LIBRARIES} diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index 67399f9a2..f1809af7f 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -103,6 +103,7 @@ main (int argc,char * argv[] ) args.s1ap_args.mnc = 0x01; args.s1ap_args.mme_bindx_addr="127.0.0.0/24"; + args.log_args.filename = std::string("/tmp/epc.log"); struct sockaddr_in enb_addr; char readbuf[1000]; struct sctp_sndrcvinfo sri; diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index c898d1a73..291077868 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -66,7 +66,18 @@ mme::cleanup(void) int mme::init(all_args_t* args) { - if(m_s1ap.init(args->s1ap_args)){ + + /*Init loggers*/ + if (!args->log_args.filename.compare("stdout")) { + m_logger = &m_logger_stdout; + } else { + m_logger_file.init(args->log_args.filename); + m_logger_file.log("\n\n"); + m_logger = &m_logger_file; + } + + m_s1ap_log.init("S1AP", m_logger); + if(m_s1ap.init(args->s1ap_args, &m_s1ap_log)){ std::cout << "Error initializing MME S1APP" << std::endl; exit(-1); } diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 2e6fc0b2b..6199fd3e9 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -32,6 +32,7 @@ #include #include #include + #include "mme/s1ap.h" namespace srsepc{ @@ -46,7 +47,7 @@ s1ap::~s1ap() } int -s1ap::init(s1ap_args_t s1ap_args) +s1ap::init(s1ap_args_t s1ap_args, srslte::log *s1ap_log) { m_mme_code = s1ap_args.mme_code ; m_mme_group = s1ap_args.mme_group; @@ -56,6 +57,8 @@ s1ap::init(s1ap_args_t s1ap_args) m_mme_bindx_addr = s1ap_args.mme_bindx_addr; m_mme_name = std::string("SRS MME"); + m_log_h = s1ap_log; + m_s1mme = enb_listen(); return 0; } @@ -83,6 +86,7 @@ s1ap::enb_listen() struct sockaddr_in s1mme_addr;//TODO make this a configurable class memeber. struct sctp_event_subscribe evnts; + m_log_h->info("Initializing S1-MME ..."); sock_fd = socket (AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); if (sock_fd == -1){ std::cout << "[S1APP] Could not create SCTP socket" < Date: Wed, 11 Oct 2017 19:24:02 +0100 Subject: [PATCH 013/172] Adding argument parsing to main.cc --- srsepc/hdr/mme/s1ap.h | 4 +- srsepc/src/main.cc | 92 ++++++++++++++++++++++++++++++++---------- srsepc/src/mme/s1ap.cc | 7 ++-- 3 files changed, 77 insertions(+), 26 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 5a3de3ac6..8388083ff 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -35,7 +35,7 @@ typedef struct{ uint16_t tac; // 16-bit tac uint16_t mcc; // BCD-coded with 0xF filler uint16_t mnc; // BCD-coded with 0xF filler - std::string mme_bindx_addr; + std::string mme_bind_addr; std::string mme_name; } s1ap_args_t; @@ -56,7 +56,7 @@ private: uint16_t m_tac; // 16-bit tac uint16_t m_mcc; // BCD-coded with 0xF filler uint16_t m_mnc; // BCD-coded with 0xF filler - std::string m_mme_bindx_addr; + std::string m_mme_bind_addr; std::string m_mme_name; srslte::log *m_log_h; diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index f1809af7f..42759749f 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -31,6 +31,7 @@ #include #include #include +#include "srslte/common/bcd_helpers.h" #include "mme/mme.h" using namespace std; @@ -44,16 +45,21 @@ sig_int_handler(int signo){ running = false; } +/********************************************************************** + * Program arguments processing + ***********************************************************************/ +string config_file; -/* void parse_args(all_args_t *args, int argc, char* argv[]) { + string mme_name; string mme_code; string mme_group; string tac; string mcc; string mnc; + string mme_bind_addr; // Command line only options bpo::options_description general("General options"); @@ -66,42 +72,86 @@ parse_args(all_args_t *args, int argc, char* argv[]) { bpo::options_description common("Configuration options"); common.add_options() - ("mme.enb_id", bpo::value(&enb_id)->default_value("0x0"), "eNodeB ID") - ("mme.name", bpo::value(&args->enb.s1ap.enb_name)->default_value("srsenb01"), "eNodeB Name") - ("mme.cell_id", bpo::value(&cell_id)->default_value("0x0"), "Cell ID") - ("mme.tac", bpo::value(&tac)->default_value("0x0"), "Tracking Area Code") - ("mme.mcc", bpo::value(&mcc)->default_value("001"), "Mobile Country Code") - ("mme.mnc", bpo::value(&mnc)->default_value("01"), "Mobile Network Code") - ("mme.mme_bindx_addr", bpo::value(&args->enb.s1ap.mme_addr)->default_value("127.0.0.1"),"IP address of MME for S1 connnection") + ("mme.mme_code", bpo::value(&mme_code)->default_value("0x01"), "MME Code") + ("mme.name", bpo::value(&mme_name)->default_value("srsmme01"), "MME Name") + ("mme.mme_group", bpo::value(&mme_group)->default_value("0x01"), "Cell ID") + ("mme.tac", bpo::value(&tac)->default_value("0x0"), "Tracking Area Code") + ("mme.mcc", bpo::value(&mcc)->default_value("001"), "Mobile Country Code") + ("mme.mnc", bpo::value(&mnc)->default_value("01"), "Mobile Network Code") + ("mme.mme_bind_addr", bpo::value(&mme_bind_addr)->default_value("127.0.0.1"),"IP address of MME for S1 connnection") ; - + + // Positional options - config file location bpo::options_description position("Positional options"); position.add_options() - ("config_file", bpo::value< string >(&config_file), "eNodeB configuration file") + ("config_file", bpo::value< string >(&config_file), "MME configuration file") ; bpo::positional_options_description p; - p.add("config_file", -1) + p.add("config_file", -1); + // these options are allowed on the command line + bpo::options_description cmdline_options; + cmdline_options.add(common).add(position).add(general); + + // parse the command line and store result in vm + bpo::variables_map vm; + bpo::store(bpo::command_line_parser(argc, argv).options(cmdline_options).positional(p).run(), vm); + bpo::notify(vm); + + // help option was given - print usage and exit + if (vm.count("help")) { + cout << "Usage: " << argv[0] << " [OPTIONS] config_file" << endl << endl; + cout << common << endl << general << endl; + exit(0); + } + //Concert hex strings + { + std::stringstream sstr; + sstr << std::hex << vm["mme.mme_group"].as(); + sstr >> args->s1ap_args.mme_group; + } + { + std::stringstream sstr; + sstr << std::hex << vm["mme.mme_code"].as(); + uint16_t tmp; // Need intermediate uint16_t as uint8_t is treated as char + sstr >> tmp; + args->s1ap_args.mme_code = tmp; + } + { + std::stringstream sstr; + sstr << std::hex << vm["mme.tac"].as(); + sstr >> args->s1ap_args.tac; + } + // Convert MCC/MNC strings + if(!srslte::string_to_mcc(mcc, &args->s1ap_args.mcc)) { + cout << "Error parsing enb.mcc:" << mcc << " - must be a 3-digit string." << endl; + } + if(!srslte::string_to_mnc(mnc, &args->s1ap_args.mnc)) { + cout << "Error parsing enb.mnc:" << mnc << " - must be a 2 or 3-digit string." << endl; + } + + args->s1ap_args.mme_bind_addr = mme_bind_addr; return; } -*/ + int main (int argc,char * argv[] ) { - cout << "--- Software Radio Systems EPC MME ---" << endl << endl; - + cout << "--- Software Radio Systems EPC ---" << endl << endl; signal(SIGINT, sig_int_handler); + all_args_t args; + parse_args(&args, argc, argv); + //TODO these should be passed from config files - all_args_t args; - args.s1ap_args.mme_code = 0x01; - args.s1ap_args.mme_group = 0x0001; - args.s1ap_args.tac = 0x0001; - args.s1ap_args.mcc = 0x01; - args.s1ap_args.mnc = 0x01; - args.s1ap_args.mme_bindx_addr="127.0.0.0/24"; + //args.s1ap_args.mme_code = 0x01; + //args.s1ap_args.mme_group = 0x0001; + //args.s1ap_args.tac = 0x0001; + //args.s1ap_args.mcc = 0x01; + //args.s1ap_args.mnc = 0x01; + //args.s1ap_args.mme_bindx_addr="127.0.0.0/24"; args.log_args.filename = std::string("/tmp/epc.log"); struct sockaddr_in enb_addr; diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 6199fd3e9..bbf36180e 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -54,7 +54,7 @@ s1ap::init(s1ap_args_t s1ap_args, srslte::log *s1ap_log) m_tac = s1ap_args.tac; m_mcc = s1ap_args.mcc; m_mnc = s1ap_args.mnc; - m_mme_bindx_addr = s1ap_args.mme_bindx_addr; + m_mme_bind_addr = s1ap_args.mme_bind_addr; m_mme_name = std::string("SRS MME"); m_log_h = s1ap_log; @@ -111,8 +111,9 @@ s1ap::enb_listen() //S1-MME bind bzero(&s1mme_addr, sizeof(s1mme_addr)); - s1mme_addr.sin_family = AF_INET; - s1mme_addr.sin_addr.s_addr = htonl(INADDR_ANY); //TODO this should use the bindx information + s1mme_addr.sin_family = AF_INET; + inet_pton(AF_INET, m_mme_bind_addr.c_str(), &(s1mme_addr.sin_addr) ); + //s1mme_addr.sin_addr.s_addr = htonl(INADDR_ANY); //TODO this should use the bindx information s1mme_addr.sin_port = htons(S1MME_PORT); err = bind(sock_fd, (struct sockaddr*) &s1mme_addr, sizeof (s1mme_addr)); if (err != 0){ From 41aafbc9c8fc5e3f04d8e4775ef3aeb4977b17d0 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 12 Oct 2017 21:53:48 +0100 Subject: [PATCH 014/172] Added initial ability to parse the S1 setup request. --- srsepc/hdr/mme/mme.h | 5 +++ srsepc/hdr/mme/s1ap.h | 7 +++ srsepc/src/CMakeLists.txt | 1 + srsepc/src/main.cc | 45 +------------------ srsepc/src/mme/mme.cc | 44 ++++++++++++++++++- srsepc/src/mme/s1ap.cc | 92 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 150 insertions(+), 44 deletions(-) diff --git a/srsepc/hdr/mme/mme.h b/srsepc/hdr/mme/mme.h index 3749eef2f..40ede136b 100644 --- a/srsepc/hdr/mme/mme.h +++ b/srsepc/hdr/mme/mme.h @@ -36,6 +36,7 @@ #include #include "srslte/common/logger_file.h" #include "srslte/common/log_filter.h" +#include "srslte/common/buffer_pool.h" #include "s1ap.h" @@ -67,6 +68,8 @@ public: void stop(); int get_s1_mme(); + + void main_loop(); private: @@ -75,6 +78,8 @@ private: static mme *m_instance; s1ap m_s1ap; + srslte::byte_buffer_pool *m_pool; + /*Logs*/ srslte::logger_stdout m_logger_stdout; srslte::logger_file m_logger_file; diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 8388083ff..46c495f6f 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -23,6 +23,7 @@ * and at http://www.gnu.org/licenses/. * */ +#include "srslte/asn1/liblte_s1ap.h" #include "srslte/common/log.h" namespace srsepc{ @@ -50,6 +51,12 @@ public: int get_s1_mme(); + bool handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu); + + bool handle_initiatingmessage(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg); + + bool handle_s1setuprequest(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg); + private: uint8_t m_mme_code; uint16_t m_mme_group; diff --git a/srsepc/src/CMakeLists.txt b/srsepc/src/CMakeLists.txt index 11985c134..fec7cd557 100644 --- a/srsepc/src/CMakeLists.txt +++ b/srsepc/src/CMakeLists.txt @@ -14,6 +14,7 @@ endif (RPATH) add_executable(srsepc main.cc ) target_link_libraries(srsepc srsepc_mme + srslte_upper srslte_common ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index 42759749f..3d4bb6949 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -2,8 +2,6 @@ * * \section COPYRIGHT * - * Copyright 2013-2017 Software Radio Systems Limited - * * \section LICENSE * * This file is part of srsLTE. @@ -26,10 +24,6 @@ #include #include #include -#include -#include -#include -#include #include #include "srslte/common/bcd_helpers.h" #include "mme/mme.h" @@ -145,21 +139,7 @@ main (int argc,char * argv[] ) all_args_t args; parse_args(&args, argc, argv); - //TODO these should be passed from config files - //args.s1ap_args.mme_code = 0x01; - //args.s1ap_args.mme_group = 0x0001; - //args.s1ap_args.tac = 0x0001; - //args.s1ap_args.mcc = 0x01; - //args.s1ap_args.mnc = 0x01; - //args.s1ap_args.mme_bindx_addr="127.0.0.0/24"; - args.log_args.filename = std::string("/tmp/epc.log"); - struct sockaddr_in enb_addr; - char readbuf[1000]; - struct sctp_sndrcvinfo sri; - socklen_t fromlen; - int rd_sz; - int msg_flags=0; mme *mme = mme::get_instance(); if (mme->init(&args)) { @@ -167,29 +147,8 @@ main (int argc,char * argv[] ) exit(1); } - //Initalize S1-MME scoket - int s1mme = mme->get_s1_mme(); - cout << "Socket: " << s1mme; - while(running) - { - cout << "Waiting for SCTP Msg on: " << s1mme << endl; - //cout << "Sri:" << sri <main_loop(); + mme->stop(); mme->cleanup(); cout << "--- exiting ---" << endl; diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index 291077868..d6f8b4359 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -25,6 +25,10 @@ */ #include //TODO Remove +#include +#include +#include +#include #include #include "mme/mme.h" @@ -35,7 +39,8 @@ boost::mutex mme_instance_mutex; mme::mme() { - return; + m_pool = srslte::byte_buffer_pool::get_instance(); + return; } mme::~mme() @@ -97,4 +102,41 @@ mme::get_s1_mme() return m_s1ap.get_s1_mme(); } +void +mme::main_loop() +{ + srslte::byte_buffer_t *pdu = m_pool->allocate(); + uint32_t sz = SRSLTE_MAX_BUFFER_SIZE_BYTES - SRSLTE_BUFFER_HEADER_OFFSET; + + struct sockaddr_in enb_addr; + struct sctp_sndrcvinfo sri; + socklen_t fromlen = sizeof(enb_addr); + bzero(&enb_addr, sizeof(enb_addr)); + int rd_sz; + int msg_flags=0; + + //Get S1-MME socket + int s1mme = m_s1ap.get_s1_mme(); + while(true) + { + std::cout << "Waiting for SCTP Msg " << std::endl; + pdu->reset(); + rd_sz = sctp_recvmsg(s1mme, pdu->msg, sz,(struct sockaddr*) &enb_addr, &fromlen, &sri, &msg_flags); + if (rd_sz == -1 && errno != EAGAIN){ + std::cout<< "Error reading from SCTP socket" << std::endl; + printf("Error: %s\n", strerror(errno)); + } + else if (rd_sz == -1 && errno == EAGAIN){ + std::cout << "Timeout reached" << std::endl; + } + else{ + pdu->N_bytes = rd_sz; + std::cout<< "Received SCTP msg." << std::endl; + std::cout << "\tSize: " << pdu->N_bytes << std::endl; + std::cout << "\tMsg: " << pdu->msg << std::endl; + m_s1ap.handle_s1ap_rx_pdu(pdu); + } + } +} + } //namespace srsepc diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index bbf36180e..495f1ca02 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -33,6 +33,7 @@ #include #include +#include "srslte/common/common.h" #include "mme/s1ap.h" namespace srsepc{ @@ -60,6 +61,7 @@ s1ap::init(s1ap_args_t s1ap_args, srslte::log *s1ap_log) m_log_h = s1ap_log; m_s1mme = enb_listen(); + return 0; } @@ -131,5 +133,95 @@ s1ap::enb_listen() return sock_fd; } +bool +s1ap::handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu) //TODO As it is, this function is exactly the same as srsenb::handle_s1ap_rx_pdu. Refactoring is needed. +{ + LIBLTE_S1AP_S1AP_PDU_STRUCT rx_pdu; + + if(liblte_s1ap_unpack_s1ap_pdu((LIBLTE_BYTE_MSG_STRUCT*)pdu, &rx_pdu) != LIBLTE_SUCCESS) { + std::cout << "Failed to Unpack PDU" << std::endl; + m_log_h->error("Failed to unpack received PDU\n"); + return false; + } + + switch(rx_pdu.choice_type) { + case LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE: + std::cout << "Received initiating PDU" <debug("Received initiating PDU\n"); + return handle_initiatingmessage(&rx_pdu.choice.initiatingMessage); + break; + case LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME: + std::cout << "Received Successful PDU" <debug("Received Succeseful Outcome PDU\n"); + return true;//handle_successfuloutcome(&rx_pdu.choice.successfulOutcome); + break; + case LIBLTE_S1AP_S1AP_PDU_CHOICE_UNSUCCESSFULOUTCOME: + std::cout << "Received Unsuccesfull PDU" <debug("Received Unsucceseful Outcome PDU\n"); + return true;//handle_unsuccessfuloutcome(&rx_pdu.choice.unsuccessfulOutcome); + break; + default: + std::cout << "Unhandled PDU type" <error("Unhandled PDU type %d\n", rx_pdu.choice_type); + return false; + } + + return true; + +} + +bool +s1ap::handle_initiatingmessage(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg) +{ + switch(msg->choice_type) { + case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_S1SETUPREQUEST: + std::cout << "Received S1 Setup Request." << std::endl; + return handle_s1setuprequest(&msg->choice.S1SetupRequest); + default: + std::cout << "Unhandled intiating message" << std::cout; + //s1ap_log->error("Unhandled intiating message: %s\n", liblte_s1ap_initiatingmessage_choice_text[msg->choice_type]); + } + return true; +} + +bool +s1ap::handle_s1setuprequest(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg) +{ + + uint8_t tmp[150]; + bzero(tmp,sizeof(tmp)); + memcpy(tmp,&msg->eNBname.buffer,msg->eNBname.n_octets); + std::cout <<"Wazuup" <eNBname); + std::cout << tmp <Global_ENB_ID.eNB_ID.choice.macroENB_ID.buffer<info("Received DownlinkNASTransport\n"); + /* + if(msg->ext) { + s1ap_log->warning("Not handling S1AP message extension\n"); + } + if(enbid_to_rnti_map.end() == enbid_to_rnti_map.find(msg->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID)) { + s1ap_log->warning("eNB_UE_S1AP_ID not found - discarding message\n"); + return false; + } + uint16_t rnti = enbid_to_rnti_map[msg->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID]; + ue_ctxt_map[rnti].MME_UE_S1AP_ID = msg->MME_UE_S1AP_ID.MME_UE_S1AP_ID; + + if(msg->HandoverRestrictionList_present) { + s1ap_log->warning("Not handling HandoverRestrictionList\n"); + } + if(msg->SubscriberProfileIDforRFP_present) { + s1ap_log->warning("Not handling SubscriberProfileIDforRFP\n"); + } + + srslte::byte_buffer_t *pdu = pool_allocate; + memcpy(pdu->msg, msg->NAS_PDU.buffer, msg->NAS_PDU.n_octets); + pdu->N_bytes = msg->NAS_PDU.n_octets; + rrc->write_dl_info(rnti, pdu); + */ + return true; +} + }//namespace srsepc From 5aa91483c5668977575a61314b9860163ed4daff Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 13 Oct 2017 19:19:45 +0100 Subject: [PATCH 015/172] Done decoding of s1 Setup message. Starting to store context and prepare a reply. --- srsepc/hdr/mme/s1ap.h | 4 +++ srsepc/src/CMakeLists.txt | 2 +- srsepc/src/mme/s1ap.cc | 70 +++++++++++++++++++++++++++++++++------ 3 files changed, 64 insertions(+), 12 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 46c495f6f..3fc211eca 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -24,6 +24,7 @@ * */ #include "srslte/asn1/liblte_s1ap.h" +#include "srslte/common/common.h" #include "srslte/common/log.h" namespace srsepc{ @@ -71,4 +72,7 @@ private: int m_s1mme; }; + + + } //namespace srsepc diff --git a/srsepc/src/CMakeLists.txt b/srsepc/src/CMakeLists.txt index fec7cd557..1acfcb6b5 100644 --- a/srsepc/src/CMakeLists.txt +++ b/srsepc/src/CMakeLists.txt @@ -23,7 +23,7 @@ target_link_libraries(srsepc srsepc_mme ${SCTP_LIBRARIES}) if (RPATH) - set_target_properties(srsenb PROPERTIES INSTALL_RPATH ".") + set_target_properties(srsepc PROPERTIES INSTALL_RPATH ".") endif (RPATH) install(TARGETS srsepc DESTINATION ${RUNTIME_DIR}) diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 495f1ca02..872d32ea0 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -33,7 +33,8 @@ #include #include -#include "srslte/common/common.h" +#include "srslte/upper/s1ap_common.h" +#include "srslte/common/bcd_helpers.h" #include "mme/s1ap.h" namespace srsepc{ @@ -188,15 +189,62 @@ bool s1ap::handle_s1setuprequest(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg) { - uint8_t tmp[150]; - bzero(tmp,sizeof(tmp)); - memcpy(tmp,&msg->eNBname.buffer,msg->eNBname.n_octets); - std::cout <<"Wazuup" <eNBname); - std::cout << tmp <Global_ENB_ID.eNB_ID.choice.macroENB_ID.buffer<info("Received DownlinkNASTransport\n"); + uint8_t enb_name[150]; + uint8_t enb_id[20]; + uint32_t plmn = 0; + std::string mnc_str, mcc_str; + uint16_t mcc, mnc; + uint16_t tac, bplmn; + uint32_t bplmns[32]; + + //eNB Name + if(msg->eNBname_present) + { + bzero(enb_name,sizeof(enb_name)); + memcpy(enb_name,&msg->eNBname.buffer,msg->eNBname.n_octets); + std::cout <<"eNB Name: " << enb_name <Global_ENB_ID.eNB_ID.choice.macroENB_ID.buffer, LIBLTE_S1AP_MACROENB_ID_BIT_STRING_LEN); + std::cout << "eNB ID: "; + for (int i=0;i < 20;i++) { + std::cout<< (uint16_t)enb_id[i]; + } + std::cout << std::endl; + //PLMN Id + ((uint8_t*)&plmn)[1] = msg->Global_ENB_ID.pLMNidentity.buffer[0]; + ((uint8_t*)&plmn)[2] = msg->Global_ENB_ID.pLMNidentity.buffer[1]; + ((uint8_t*)&plmn)[3] = msg->Global_ENB_ID.pLMNidentity.buffer[2]; + + plmn = ntohl(plmn); + srslte::s1ap_plmn_to_mccmnc(plmn, &mcc, &mnc); + srslte::mnc_to_string(mnc, &mnc_str); + srslte::mnc_to_string(mcc, &mcc_str); + std::cout << "MCC: "<< mcc_str << " MNC: " << mnc_str << std::endl; + + //SupportedTAs + for(uint16_t i=0; iSupportedTAs.len; i++) + { + //tac = msg->SupportedTAs.buffer[i].tAC.buffer[]; //broadcastPLMNs + ((uint8_t*)&tac)[0] = msg->SupportedTAs.buffer[i].tAC.buffer[0]; + ((uint8_t*)&tac)[1] = msg->SupportedTAs.buffer[i].tAC.buffer[1]; + std::cout << "TAC: " << ntohs(tac) << std::endl; + for (uint16_t j=0; jSupportedTAs.buffer[i].broadcastPLMNs.len; j++) + { + ((uint8_t*)&bplmns[j])[1] = msg->SupportedTAs.buffer[i].broadcastPLMNs.buffer[j].buffer[0]; + ((uint8_t*)&bplmns[j])[2] = msg->SupportedTAs.buffer[i].broadcastPLMNs.buffer[j].buffer[1]; + ((uint8_t*)&bplmns[j])[3] = msg->SupportedTAs.buffer[i].broadcastPLMNs.buffer[j].buffer[2]; + + bplmns[j] = ntohl(bplmns[j]); + srslte::mnc_to_string(mnc, &mnc_str); + srslte::mnc_to_string(mcc, &mcc_str); + std::cout << "B_MCC: "<< mcc_str << " B_MNC: " << mnc_str << std::endl; + } + } + + //Default Paging DRX + LIBLTE_S1AP_PAGINGDRX_ENUM drx = msg->DefaultPagingDRX.e; + std::cout << "Default Paging DRX" << drx << std::endl; /* if(msg->ext) { s1ap_log->warning("Not handling S1AP message extension\n"); @@ -224,4 +272,4 @@ s1ap::handle_s1setuprequest(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg) } -}//namespace srsepc +} //namespace srsepc From adf176449680cb166e09e1a443563254d3994240 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 16 Oct 2017 13:03:33 +0100 Subject: [PATCH 016/172] added plmn to MCCMNC in the srslte lib --- lib/include/srslte/common/bcd_helpers.h | 72 +++++++++++++++++++++++++ srsepc/src/mme/mme.cc | 3 ++ srsepc/src/mme/s1ap.cc | 21 ++------ 3 files changed, 78 insertions(+), 18 deletions(-) diff --git a/lib/include/srslte/common/bcd_helpers.h b/lib/include/srslte/common/bcd_helpers.h index b696954c2..10bed4347 100644 --- a/lib/include/srslte/common/bcd_helpers.h +++ b/lib/include/srslte/common/bcd_helpers.h @@ -120,6 +120,78 @@ inline std::string plmn_id_to_string(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) { return mcc_str + mnc_str; } +/****************************************************************************** + * Convert PLMN to BCD-coded MCC and MNC. + * Digits are represented by 4-bit nibbles. Unused nibbles are filled with 0xF. + * MNC 001 represented as 0xF001 + * MNC 01 represented as 0xFF01 + * PLMN encoded as per TS 36.413 sec 9.2.3.8 + *****************************************************************************/ +inline void s1ap_plmn_to_mccmnc(uint32_t plmn, uint16_t *mcc, uint16_t *mnc) +{ + uint8_t nibbles[6]; + nibbles[0] = (plmn & 0xF00000) >> 20; + nibbles[1] = (plmn & 0x0F0000) >> 16; + nibbles[2] = (plmn & 0x00F000) >> 12; + nibbles[3] = (plmn & 0x000F00) >> 8; + nibbles[4] = (plmn & 0x0000F0) >> 4; + nibbles[5] = (plmn & 0x00000F); + + *mcc = 0xF000; + *mnc = 0xF000; + *mcc |= nibbles[1] << 8; // MCC digit 1 + *mcc |= nibbles[0] << 4; // MCC digit 2 + *mcc |= nibbles[3]; // MCC digit 3 + + if(nibbles[2] == 0xF) { + // 2-digit MNC + *mnc |= 0x0F00; // MNC digit 1 + *mnc |= nibbles[5] << 4; // MNC digit 2 + *mnc |= nibbles[4]; // MNC digit 3 + } else { + // 3-digit MNC + *mnc |= nibbles[5] << 8; // MNC digit 1 + *mnc |= nibbles[4] << 4; // MNC digit 2 + *mnc |= nibbles[2] ; // MNC digit 3 + } +} + +/****************************************************************************** + * Convert BCD-coded MCC and MNC to PLMN. + * Digits are represented by 4-bit nibbles. Unused nibbles are filled with 0xF. + * MNC 001 represented as 0xF001 + * MNC 01 represented as 0xFF01 + * PLMN encoded as per TS 36.413 sec 9.2.3.8 + *****************************************************************************/ +inline void s1ap_mccmnc_to_plmn(uint16_t mcc, uint16_t mnc, uint32_t *plmn) +{ + uint8_t nibbles[6]; + nibbles[1] = (mcc & 0x0F00) >> 8; // MCC digit 1 + nibbles[0] = (mcc & 0x00F0) >> 4; // MCC digit 2 + nibbles[3] = (mcc & 0x000F); // MCC digit 3 + + if((mnc & 0xFF00) == 0xFF00) { + // 2-digit MNC + nibbles[2] = 0x0F; // MNC digit 1 + nibbles[5] = (mnc & 0x00F0) >> 4; // MNC digit 2 + nibbles[4] = (mnc & 0x000F); // MNC digit 3 + } else { + // 3-digit MNC + nibbles[5] = (mnc & 0x0F00) >> 8; // MNC digit 1 + nibbles[4] = (mnc & 0x00F0) >> 4; // MNC digit 2 + nibbles[2] = (mnc & 0x000F); // MNC digit 3 + } + + *plmn = 0x000000; + *plmn |= nibbles[0] << 20; + *plmn |= nibbles[1] << 16; + *plmn |= nibbles[2] << 12; + *plmn |= nibbles[3] << 8; + *plmn |= nibbles[4] << 4; + *plmn |= nibbles[5]; +} + + } // namespace srslte #endif // BCD_HELPERS diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index d6f8b4359..f1221d8a5 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -135,6 +135,9 @@ mme::main_loop() std::cout << "\tSize: " << pdu->N_bytes << std::endl; std::cout << "\tMsg: " << pdu->msg << std::endl; m_s1ap.handle_s1ap_rx_pdu(pdu); + sctp_send(s1mme, "OK", 2, &sri, 0); + + } } } diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 872d32ea0..4ced90566 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -33,7 +33,7 @@ #include #include -#include "srslte/upper/s1ap_common.h" +//#include "srslte/upper/s1ap_common.h" #include "srslte/common/bcd_helpers.h" #include "mme/s1ap.h" @@ -245,24 +245,9 @@ s1ap::handle_s1setuprequest(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg) //Default Paging DRX LIBLTE_S1AP_PAGINGDRX_ENUM drx = msg->DefaultPagingDRX.e; std::cout << "Default Paging DRX" << drx << std::endl; + + /* - if(msg->ext) { - s1ap_log->warning("Not handling S1AP message extension\n"); - } - if(enbid_to_rnti_map.end() == enbid_to_rnti_map.find(msg->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID)) { - s1ap_log->warning("eNB_UE_S1AP_ID not found - discarding message\n"); - return false; - } - uint16_t rnti = enbid_to_rnti_map[msg->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID]; - ue_ctxt_map[rnti].MME_UE_S1AP_ID = msg->MME_UE_S1AP_ID.MME_UE_S1AP_ID; - - if(msg->HandoverRestrictionList_present) { - s1ap_log->warning("Not handling HandoverRestrictionList\n"); - } - if(msg->SubscriberProfileIDforRFP_present) { - s1ap_log->warning("Not handling SubscriberProfileIDforRFP\n"); - } - srslte::byte_buffer_t *pdu = pool_allocate; memcpy(pdu->msg, msg->NAS_PDU.buffer, msg->NAS_PDU.n_octets); pdu->N_bytes = msg->NAS_PDU.n_octets; From 2bfb008bd28f22b78ed90cde3e63416683c936e3 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 17 Oct 2017 12:32:34 +0100 Subject: [PATCH 017/172] MME now replies with S1 Setup falure. --- srsepc/hdr/mme/mme.h | 1 + srsepc/hdr/mme/s1ap.h | 10 +++-- srsepc/src/main.cc | 2 +- srsepc/src/mme/mme.cc | 7 +++- srsepc/src/mme/s1ap.cc | 86 +++++++++++++++++++++++++++++++----------- 5 files changed, 76 insertions(+), 30 deletions(-) diff --git a/srsepc/hdr/mme/mme.h b/srsepc/hdr/mme/mme.h index 40ede136b..0ee53d4ca 100644 --- a/srsepc/hdr/mme/mme.h +++ b/srsepc/hdr/mme/mme.h @@ -34,6 +34,7 @@ #define MME_H #include +#include "srslte/common/log.h" #include "srslte/common/logger_file.h" #include "srslte/common/log_filter.h" #include "srslte/common/buffer_pool.h" diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 3fc211eca..f516b562f 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -52,11 +52,13 @@ public: int get_s1_mme(); - bool handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu); + bool handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb_sri); - bool handle_initiatingmessage(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg); + bool handle_initiatingmessage(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri); - bool handle_s1setuprequest(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg); + bool handle_s1setuprequest(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri); + + bool send_s1setupfailure(struct sctp_sndrcvinfo *enb_sri); private: uint8_t m_mme_code; @@ -67,7 +69,7 @@ private: std::string m_mme_bind_addr; std::string m_mme_name; - srslte::log *m_log_h; + srslte::log *m_s1ap_log; int m_s1mme; }; diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index 3d4bb6949..6b2ca1800 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -146,7 +146,7 @@ main (int argc,char * argv[] ) cout << "Error initializing MME" << endl; exit(1); } - + mme->main_loop(); mme->stop(); diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index f1221d8a5..35e68e5ac 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -82,10 +82,13 @@ mme::init(all_args_t* args) } m_s1ap_log.init("S1AP", m_logger); + m_s1ap_log.set_level(srslte::LOG_LEVEL_DEBUG); + m_s1ap_log.set_hex_limit(32); if(m_s1ap.init(args->s1ap_args, &m_s1ap_log)){ std::cout << "Error initializing MME S1APP" << std::endl; exit(-1); } + m_s1ap_log.console("Initialized MME\n"); return 0; } @@ -134,7 +137,7 @@ mme::main_loop() std::cout<< "Received SCTP msg." << std::endl; std::cout << "\tSize: " << pdu->N_bytes << std::endl; std::cout << "\tMsg: " << pdu->msg << std::endl; - m_s1ap.handle_s1ap_rx_pdu(pdu); + m_s1ap.handle_s1ap_rx_pdu(pdu,&sri); sctp_send(s1mme, "OK", 2, &sri, 0); @@ -142,4 +145,4 @@ mme::main_loop() } } -} //namespace srsepc +} //namespace srsepe< diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 4ced90566..7fa521e40 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -57,12 +57,13 @@ s1ap::init(s1ap_args_t s1ap_args, srslte::log *s1ap_log) m_mcc = s1ap_args.mcc; m_mnc = s1ap_args.mnc; m_mme_bind_addr = s1ap_args.mme_bind_addr; - m_mme_name = std::string("SRS MME"); + m_mme_name = std::string("srsmme0"); - m_log_h = s1ap_log; + m_s1ap_log = s1ap_log; m_s1mme = enb_listen(); - + + m_s1ap_log->console("Initialized S1-APP\n"); return 0; } @@ -86,13 +87,13 @@ s1ap::enb_listen() { /*This function sets up the SCTP socket for eNBs to connect to*/ int sock_fd, err; - struct sockaddr_in s1mme_addr;//TODO make this a configurable class memeber. + struct sockaddr_in s1mme_addr; struct sctp_event_subscribe evnts; - m_log_h->info("Initializing S1-MME ..."); + m_s1ap_log->console("Initializing S1-MME\n"); sock_fd = socket (AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); if (sock_fd == -1){ - std::cout << "[S1APP] Could not create SCTP socket" <console("Could not create SCTP socket\n"); return -1; } @@ -101,14 +102,14 @@ s1ap::enb_listen() timeout.tv_sec = 1; timeout.tv_usec = 0; if (setsockopt (sock_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0){ - std::cout << "Set socket timeout failed" << std::endl; + m_s1ap_log->console("Set socket timeout failed\n"); return -1; } bzero (&evnts, sizeof (evnts)) ; evnts.sctp_data_io_event = 1; if(setsockopt(sock_fd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof (evnts))){ - std::cout << "Subscribing to sctp_data_io_events failed" << std::cout; + m_s1ap_log->console("Subscribing to sctp_data_io_events failed\n"); return -1; } @@ -135,35 +136,30 @@ s1ap::enb_listen() } bool -s1ap::handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu) //TODO As it is, this function is exactly the same as srsenb::handle_s1ap_rx_pdu. Refactoring is needed. +s1ap::handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb_sri) { LIBLTE_S1AP_S1AP_PDU_STRUCT rx_pdu; if(liblte_s1ap_unpack_s1ap_pdu((LIBLTE_BYTE_MSG_STRUCT*)pdu, &rx_pdu) != LIBLTE_SUCCESS) { - std::cout << "Failed to Unpack PDU" << std::endl; - m_log_h->error("Failed to unpack received PDU\n"); + m_s1ap_log->console("Failed to unpack received PDU\n"); return false; } switch(rx_pdu.choice_type) { case LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE: - std::cout << "Received initiating PDU" <debug("Received initiating PDU\n"); - return handle_initiatingmessage(&rx_pdu.choice.initiatingMessage); + m_s1ap_log->console("Received initiating PDU\n"); + return handle_initiatingmessage(&rx_pdu.choice.initiatingMessage, enb_sri); break; case LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME: - std::cout << "Received Successful PDU" <debug("Received Succeseful Outcome PDU\n"); + m_s1ap_log->console("Received Succeseful Outcome PDU\n"); return true;//handle_successfuloutcome(&rx_pdu.choice.successfulOutcome); break; case LIBLTE_S1AP_S1AP_PDU_CHOICE_UNSUCCESSFULOUTCOME: - std::cout << "Received Unsuccesfull PDU" <debug("Received Unsucceseful Outcome PDU\n"); + m_s1ap_log->console("Received Unsucceseful Outcome PDU\n"); return true;//handle_unsuccessfuloutcome(&rx_pdu.choice.unsuccessfulOutcome); break; default: - std::cout << "Unhandled PDU type" <error("Unhandled PDU type %d\n", rx_pdu.choice_type); + m_s1ap_log->console("Unhandled PDU type %d\n", rx_pdu.choice_type); return false; } @@ -172,12 +168,12 @@ s1ap::handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu) //TODO As it is, this funct } bool -s1ap::handle_initiatingmessage(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg) +s1ap::handle_initiatingmessage(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri) { switch(msg->choice_type) { case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_S1SETUPREQUEST: std::cout << "Received S1 Setup Request." << std::endl; - return handle_s1setuprequest(&msg->choice.S1SetupRequest); + return handle_s1setuprequest(&msg->choice.S1SetupRequest, enb_sri); default: std::cout << "Unhandled intiating message" << std::cout; //s1ap_log->error("Unhandled intiating message: %s\n", liblte_s1ap_initiatingmessage_choice_text[msg->choice_type]); @@ -186,7 +182,7 @@ s1ap::handle_initiatingmessage(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg) } bool -s1ap::handle_s1setuprequest(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg) +s1ap::handle_s1setuprequest(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri) { uint8_t enb_name[150]; @@ -247,6 +243,9 @@ s1ap::handle_s1setuprequest(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg) std::cout << "Default Paging DRX" << drx << std::endl; + send_s1setupfailure(enb_sri); + //sctp_send(m_s1mme,"OK",2,enb_sri,0); + /* srslte::byte_buffer_t *pdu = pool_allocate; memcpy(pdu->msg, msg->NAS_PDU.buffer, msg->NAS_PDU.n_octets); @@ -256,5 +255,46 @@ s1ap::handle_s1setuprequest(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg) return true; } +bool +s1ap::send_s1setupfailure(struct sctp_sndrcvinfo *enb_sri) +{ + srslte::byte_buffer_t msg; + LIBLTE_S1AP_S1AP_PDU_STRUCT pdu; + bzero(&pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); + + pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_UNSUCCESSFULOUTCOME; + + LIBLTE_S1AP_UNSUCCESSFULOUTCOME_STRUCT *unsucc = &pdu.choice.unsuccessfulOutcome; + unsucc->procedureCode = LIBLTE_S1AP_PROC_ID_S1SETUP; + unsucc->criticality = LIBLTE_S1AP_CRITICALITY_REJECT; + unsucc->choice_type = LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_S1SETUPFAILURE; + + LIBLTE_S1AP_MESSAGE_S1SETUPFAILURE_STRUCT* s1_fail=(LIBLTE_S1AP_MESSAGE_S1SETUPFAILURE_STRUCT*)&unsucc->choice; + + s1_fail->TimeToWait_present=false; + s1_fail->CriticalityDiagnostics_present=false; + s1_fail->Cause.ext=false; + s1_fail->Cause.choice_type = LIBLTE_S1AP_CAUSE_CHOICE_MISC; + s1_fail->Cause.choice.misc.ext=false; + s1_fail->Cause.choice.misc.e=LIBLTE_S1AP_CAUSEMISC_UNKNOWN_PLMN; + + liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)&msg); + + ssize_t n_sent = sctp_send(m_s1mme,msg.msg, msg.N_bytes, enb_sri, 0); + + if(n_sent == -1) + { + m_s1ap_log->console("Failed to send S1 Setup Failure"); + return false; + } + return true; +} + +/* +bool +s1ap::setup_enb_ctx() +{ + return false; +}*/ } //namespace srsepc From 26f03a49f31e06fbdb80a79fa9114c81dd5cb06f Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 17 Oct 2017 18:13:20 +0100 Subject: [PATCH 018/172] Intial code for S1 setup response --- srsepc/hdr/mme/s1ap.h | 3 +- srsepc/src/mme/s1ap.cc | 77 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 70 insertions(+), 10 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index f516b562f..e03affd75 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -59,7 +59,8 @@ public: bool handle_s1setuprequest(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri); bool send_s1setupfailure(struct sctp_sndrcvinfo *enb_sri); - + + bool send_s1setupresponse(struct sctp_sndrcvinfo *enb_sri); private: uint8_t m_mme_code; uint16_t m_mme_group; diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 7fa521e40..de36eccda 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -242,16 +242,8 @@ s1ap::handle_s1setuprequest(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, stru LIBLTE_S1AP_PAGINGDRX_ENUM drx = msg->DefaultPagingDRX.e; std::cout << "Default Paging DRX" << drx << std::endl; - send_s1setupfailure(enb_sri); - //sctp_send(m_s1mme,"OK",2,enb_sri,0); - - /* - srslte::byte_buffer_t *pdu = pool_allocate; - memcpy(pdu->msg, msg->NAS_PDU.buffer, msg->NAS_PDU.n_octets); - pdu->N_bytes = msg->NAS_PDU.n_octets; - rrc->write_dl_info(rnti, pdu); - */ + return true; } @@ -290,6 +282,73 @@ s1ap::send_s1setupfailure(struct sctp_sndrcvinfo *enb_sri) return true; } + +bool +s1ap::send_s1setupresponse(struct sctp_sndrcvinfo *enb_sri) +{ + srslte::byte_buffer_t msg; + LIBLTE_S1AP_S1AP_PDU_STRUCT pdu; + bzero(&pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); + + pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME; + + LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *succ = &pdu.choice.successfulOutcome; + succ->procedureCode = LIBLTE_S1AP_PROC_ID_S1SETUP; + succ->criticality = LIBLTE_S1AP_CRITICALITY_REJECT; + succ->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_S1SETUPRESPONSE; + + LIBLTE_S1AP_MESSAGE_S1SETUPRESPONSE_STRUCT* s1_resp=(LIBLTE_S1AP_MESSAGE_S1SETUPRESPONSE_STRUCT*)&succ->choice; + + s1_resp->ext=false; + + //MME Name + s1_resp->MMEname_present=true; + s1_resp->MMEname.ext=false; + s1_resp->MMEname.n_octets=m_mme_name.length(); + memcpy(s1_resp->MMEname.buffer,m_mme_name.c_str(),m_mme_name.length()); + + //Served GUMEIs + s1_resp->ServedGUMMEIs.len=1;//TODO Only one served GUMMEI supported + LIBLTE_S1AP_SERVEDGUMMEISITEM_STRUCT *serv_gummei = &s1_resp->ServedGUMMEIs.buffer[0]; + + serv_gummei->ext=false; + //serv_gummei->iE_Extensions=false; + + uint32_t plmn=0; + srslte::s1ap_mccmnc_to_plmn(m_mcc, m_mnc, &plmn); + plmn=htonl(plmn); + serv_gummei->servedPLMNs.len = 1; //Only one PLMN supported + serv_gummei->servedPLMNs.buffer[0].buffer[0]=((uint8_t*)&plmn)[1]; + serv_gummei->servedPLMNs.buffer[0].buffer[1]=((uint8_t*)&plmn)[2]; + serv_gummei->servedPLMNs.buffer[0].buffer[2]=((uint8_t*)&plmn)[3]; + + serv_gummei->servedGroupIDs.len=1; //LIBLTE_S1AP_SERVEDGROUPIDS_STRUCT + uint16_t tmp=htons(m_mme_group); + serv_gummei->servedGroupIDs.buffer[0].buffer[0]=((uint8_t*)&tmp)[0]; + serv_gummei->servedGroupIDs.buffer[0].buffer[1]=((uint8_t*)&tmp)[1]; + + serv_gummei->servedMMECs.len=1; //Only one MMEC served + serv_gummei->servedMMECs.buffer[0].buffer[0]=m_mme_code; + + //Relative MME Capacity + s1_resp->RelativeMMECapacity.RelativeMMECapacity=255; + + //Relay Unsupported + s1_resp->MMERelaySupportIndicator_present=false; + + liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)&msg); + + ssize_t n_sent = sctp_send(m_s1mme,msg.msg, msg.N_bytes, enb_sri, 0); + + if(n_sent == -1) + { + m_s1ap_log->console("Failed to send S1 Setup Failure"); + return false; + } + return true; +} + + /* bool s1ap::setup_enb_ctx() From 91fd66fe9a69637d30d145bf0ec88da7182c1ce3 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 17 Oct 2017 18:40:04 +0100 Subject: [PATCH 019/172] Small bug fix. --- srsepc/src/mme/mme.cc | 2 -- srsepc/src/mme/s1ap.cc | 6 +++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index 35e68e5ac..d1293855c 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -138,8 +138,6 @@ mme::main_loop() std::cout << "\tSize: " << pdu->N_bytes << std::endl; std::cout << "\tMsg: " << pdu->msg << std::endl; m_s1ap.handle_s1ap_rx_pdu(pdu,&sri); - sctp_send(s1mme, "OK", 2, &sri, 0); - } } diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index de36eccda..cd4b58c9b 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -242,8 +242,8 @@ s1ap::handle_s1setuprequest(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, stru LIBLTE_S1AP_PAGINGDRX_ENUM drx = msg->DefaultPagingDRX.e; std::cout << "Default Paging DRX" << drx << std::endl; - send_s1setupfailure(enb_sri); - + //send_s1setupfailure(enb_sri); + send_s1setupresponse(enb_sri); return true; } @@ -294,7 +294,7 @@ s1ap::send_s1setupresponse(struct sctp_sndrcvinfo *enb_sri) LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *succ = &pdu.choice.successfulOutcome; succ->procedureCode = LIBLTE_S1AP_PROC_ID_S1SETUP; - succ->criticality = LIBLTE_S1AP_CRITICALITY_REJECT; + succ->criticality = LIBLTE_S1AP_CRITICALITY_IGNORE; succ->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_S1SETUPRESPONSE; LIBLTE_S1AP_MESSAGE_S1SETUPRESPONSE_STRUCT* s1_resp=(LIBLTE_S1AP_MESSAGE_S1SETUPRESPONSE_STRUCT*)&succ->choice; From 4307a5aef2ed439f9e6ea2ea4bb68b572f06fea8 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 18 Oct 2017 14:33:58 +0100 Subject: [PATCH 020/172] Removing the timeout of the socket. --- srsepc/src/mme/s1ap.cc | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index cd4b58c9b..08937142e 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -97,15 +97,7 @@ s1ap::enb_listen() return -1; } - //Set timeout - struct timeval timeout; - timeout.tv_sec = 1; - timeout.tv_usec = 0; - if (setsockopt (sock_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0){ - m_s1ap_log->console("Set socket timeout failed\n"); - return -1; - } - + //Sets the data_io_event to be able to use sendrecv_info bzero (&evnts, sizeof (evnts)) ; evnts.sctp_data_io_event = 1; if(setsockopt(sock_fd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof (evnts))){ From 4f6fafb66d9bc5bf845e98955f849eeaa87d5509 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 18 Oct 2017 15:27:21 +0100 Subject: [PATCH 021/172] General code cleanup --- srsepc/hdr/mme/mme.h | 12 +++++------- srsepc/src/main.cc | 10 +++++++--- srsepc/src/mme/mme.cc | 31 +++++++++++++++++++------------ 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/srsepc/hdr/mme/mme.h b/srsepc/hdr/mme/mme.h index 0ee53d4ca..b2c67df3d 100644 --- a/srsepc/hdr/mme/mme.h +++ b/srsepc/hdr/mme/mme.h @@ -38,6 +38,7 @@ #include "srslte/common/logger_file.h" #include "srslte/common/log_filter.h" #include "srslte/common/buffer_pool.h" +#include "srslte/common/threads.h" #include "s1ap.h" @@ -57,20 +58,16 @@ typedef struct{ } all_args_t; -class mme +class mme: + public thread { public: static mme* get_instance(void); - static void cleanup(void); - int init(all_args_t* args); - void stop(); - int get_s1_mme(); - - void main_loop(); + void run_thread(); private: @@ -79,6 +76,7 @@ private: static mme *m_instance; s1ap m_s1ap; + bool m_running; srslte::byte_buffer_pool *m_pool; /*Logs*/ diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index 6b2ca1800..4920519dc 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -134,7 +134,7 @@ int main (int argc,char * argv[] ) { cout << "--- Software Radio Systems EPC ---" << endl << endl; - signal(SIGINT, sig_int_handler); + signal(SIGINT, sig_int_handler); all_args_t args; parse_args(&args, argc, argv); @@ -146,11 +146,15 @@ main (int argc,char * argv[] ) cout << "Error initializing MME" << endl; exit(1); } + mme->start(); - mme->main_loop(); - + while(running) { + sleep(0.5); + } + mme->stop(); mme->cleanup(); + cout << "--- exiting ---" << endl; return 0; } diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index d1293855c..8205c408a 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -37,7 +37,8 @@ namespace srsepc{ mme* mme::m_instance = NULL; boost::mutex mme_instance_mutex; -mme::mme() +mme::mme(): + m_running(false) { m_pool = srslte::byte_buffer_pool::get_instance(); return; @@ -71,7 +72,6 @@ mme::cleanup(void) int mme::init(all_args_t* args) { - /*Init loggers*/ if (!args->log_args.filename.compare("stdout")) { m_logger = &m_logger_stdout; @@ -95,6 +95,12 @@ mme::init(all_args_t* args) void mme::stop() { + if(m_running) + { + m_running = false; + thread_cancel(); + wait_thread_finish(); + } m_s1ap.stop(); return; } @@ -106,7 +112,7 @@ mme::get_s1_mme() } void -mme::main_loop() +mme::run_thread() { srslte::byte_buffer_t *pdu = m_pool->allocate(); uint32_t sz = SRSLTE_MAX_BUFFER_SIZE_BYTES - SRSLTE_BUFFER_HEADER_OFFSET; @@ -118,29 +124,30 @@ mme::main_loop() int rd_sz; int msg_flags=0; + //Mark the thread as running + m_running=true; + //Get S1-MME socket int s1mme = m_s1ap.get_s1_mme(); - while(true) + while(m_running) { - std::cout << "Waiting for SCTP Msg " << std::endl; + //std::cout << "Waiting for SCTP Msg " << std::endl; + m_s1ap_log.debug("Waiting for SCTP Msg"); pdu->reset(); rd_sz = sctp_recvmsg(s1mme, pdu->msg, sz,(struct sockaddr*) &enb_addr, &fromlen, &sri, &msg_flags); if (rd_sz == -1 && errno != EAGAIN){ - std::cout<< "Error reading from SCTP socket" << std::endl; - printf("Error: %s\n", strerror(errno)); + m_s1ap_log.error("Error reading from SCTP socket: %s", strerror(errno)); } else if (rd_sz == -1 && errno == EAGAIN){ - std::cout << "Timeout reached" << std::endl; + m_s1ap_log("Socket timeout reached"); } else{ pdu->N_bytes = rd_sz; - std::cout<< "Received SCTP msg." << std::endl; - std::cout << "\tSize: " << pdu->N_bytes << std::endl; - std::cout << "\tMsg: " << pdu->msg << std::endl; + m_s1ap_log("Received S1AP msg. Size: %d", pdu->N_bytes); m_s1ap.handle_s1ap_rx_pdu(pdu,&sri); - } } + return; } } //namespace srsepe< From d8436ea2fcf23a56a9c2409eb285cc3bab534608 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 19 Oct 2017 14:47:41 +0100 Subject: [PATCH 022/172] A bit of code cleanup --- srsepc/hdr/mme/s1ap.h | 26 +++++++++++++--- srsepc/src/mme/mme.cc | 16 +++++----- srsepc/src/mme/s1ap.cc | 70 +++++++++++++++++++++++------------------- 3 files changed, 68 insertions(+), 44 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index e03affd75..9b3c546c6 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -23,10 +23,22 @@ * and at http://www.gnu.org/licenses/. * */ +#ifndef S1AP_H +#define S1AP_H + #include "srslte/asn1/liblte_s1ap.h" #include "srslte/common/common.h" #include "srslte/common/log.h" +#include +#include +#include +#include +#include +#include + +#include "mme/s1ap_mngmt_proc.h" + namespace srsepc{ const uint16_t S1MME_PORT = 36412; @@ -54,28 +66,34 @@ public: bool handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb_sri); - bool handle_initiatingmessage(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri); + bool handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri); - bool handle_s1setuprequest(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri); + bool handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri); - bool send_s1setupfailure(struct sctp_sndrcvinfo *enb_sri); + bool send_s1_setup_failure(struct sctp_sndrcvinfo *enb_sri); - bool send_s1setupresponse(struct sctp_sndrcvinfo *enb_sri); + bool send_s1_setup_response(struct sctp_sndrcvinfo *enb_sri); + private: uint8_t m_mme_code; uint16_t m_mme_group; uint16_t m_tac; // 16-bit tac uint16_t m_mcc; // BCD-coded with 0xF filler uint16_t m_mnc; // BCD-coded with 0xF filler + uint32_t m_plmn; + std::string m_mme_bind_addr; std::string m_mme_name; srslte::log *m_s1ap_log; int m_s1mme; + s1ap_mngmt_proc m_s1ap_mngmt_proc; }; } //namespace srsepc + +#endif //S1AP_H diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index 8205c408a..cdea2f170 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -77,7 +77,7 @@ mme::init(all_args_t* args) m_logger = &m_logger_stdout; } else { m_logger_file.init(args->log_args.filename); - m_logger_file.log("\n\n"); + m_logger_file.log("\n--- Software Radio Systems MME log ---\n\n"); m_logger = &m_logger_file; } @@ -85,10 +85,11 @@ mme::init(all_args_t* args) m_s1ap_log.set_level(srslte::LOG_LEVEL_DEBUG); m_s1ap_log.set_hex_limit(32); if(m_s1ap.init(args->s1ap_args, &m_s1ap_log)){ - std::cout << "Error initializing MME S1APP" << std::endl; + m_s1ap_log.error("Error initializing MME S1APP\n"); exit(-1); } - m_s1ap_log.console("Initialized MME\n"); + m_s1ap_log.info("Initialized S1-MME\n"); + m_s1ap_log.console("Initialized S1-MME\n"); return 0; } @@ -131,23 +132,22 @@ mme::run_thread() int s1mme = m_s1ap.get_s1_mme(); while(m_running) { - //std::cout << "Waiting for SCTP Msg " << std::endl; - m_s1ap_log.debug("Waiting for SCTP Msg"); + m_s1ap_log.debug("Waiting for SCTP Msg\n"); pdu->reset(); rd_sz = sctp_recvmsg(s1mme, pdu->msg, sz,(struct sockaddr*) &enb_addr, &fromlen, &sri, &msg_flags); if (rd_sz == -1 && errno != EAGAIN){ m_s1ap_log.error("Error reading from SCTP socket: %s", strerror(errno)); } else if (rd_sz == -1 && errno == EAGAIN){ - m_s1ap_log("Socket timeout reached"); + m_s1ap_log.debug("Socket timeout reached"); } else{ pdu->N_bytes = rd_sz; - m_s1ap_log("Received S1AP msg. Size: %d", pdu->N_bytes); + m_s1ap_log.info("Received S1AP msg. Size: %d\n", pdu->N_bytes); m_s1ap.handle_s1ap_rx_pdu(pdu,&sri); } } return; } -} //namespace srsepe< +} //namespace srsepc diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 08937142e..5f410c62a 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -26,14 +26,6 @@ #include //TODO Remove -#include -#include -#include -#include -#include -#include - -//#include "srslte/upper/s1ap_common.h" #include "srslte/common/bcd_helpers.h" #include "mme/s1ap.h" @@ -59,11 +51,12 @@ s1ap::init(s1ap_args_t s1ap_args, srslte::log *s1ap_log) m_mme_bind_addr = s1ap_args.mme_bind_addr; m_mme_name = std::string("srsmme0"); + srslte::s1ap_mccmnc_to_plmn(m_mcc, m_mnc, &m_plmn); + m_s1ap_log = s1ap_log; m_s1mme = enb_listen(); - m_s1ap_log->console("Initialized S1-APP\n"); return 0; } @@ -109,18 +102,19 @@ s1ap::enb_listen() bzero(&s1mme_addr, sizeof(s1mme_addr)); s1mme_addr.sin_family = AF_INET; inet_pton(AF_INET, m_mme_bind_addr.c_str(), &(s1mme_addr.sin_addr) ); - //s1mme_addr.sin_addr.s_addr = htonl(INADDR_ANY); //TODO this should use the bindx information s1mme_addr.sin_port = htons(S1MME_PORT); err = bind(sock_fd, (struct sockaddr*) &s1mme_addr, sizeof (s1mme_addr)); if (err != 0){ - std::cout << "Error binding SCTP socket" << std::endl; + m_s1ap_log->error("Error binding SCTP socket\n"); + m_s1ap_log->console("Error binding SCTP socket\n"); return -1; } //Listen for connections err = listen(sock_fd,SOMAXCONN); if (err != 0){ - std::cout << "Error in SCTP socket listen" << std::endl; + m_s1ap_log->error("Error in SCTP socket listen\n"); + m_s1ap_log->console("Error in SCTP socket listen\n"); return -1; } @@ -133,14 +127,14 @@ s1ap::handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb LIBLTE_S1AP_S1AP_PDU_STRUCT rx_pdu; if(liblte_s1ap_unpack_s1ap_pdu((LIBLTE_BYTE_MSG_STRUCT*)pdu, &rx_pdu) != LIBLTE_SUCCESS) { - m_s1ap_log->console("Failed to unpack received PDU\n"); + m_s1ap_log->error("Failed to unpack received PDU\n"); return false; } switch(rx_pdu.choice_type) { case LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE: m_s1ap_log->console("Received initiating PDU\n"); - return handle_initiatingmessage(&rx_pdu.choice.initiatingMessage, enb_sri); + return handle_initiating_message(&rx_pdu.choice.initiatingMessage, enb_sri); break; case LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME: m_s1ap_log->console("Received Succeseful Outcome PDU\n"); @@ -160,21 +154,20 @@ s1ap::handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb } bool -s1ap::handle_initiatingmessage(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri) +s1ap::handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri) { switch(msg->choice_type) { case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_S1SETUPREQUEST: - std::cout << "Received S1 Setup Request." << std::endl; - return handle_s1setuprequest(&msg->choice.S1SetupRequest, enb_sri); + m_s1ap_log->info("Received S1 Setup Request.\n"); + return handle_s1_setup_request(&msg->choice.S1SetupRequest, enb_sri); default: - std::cout << "Unhandled intiating message" << std::cout; - //s1ap_log->error("Unhandled intiating message: %s\n", liblte_s1ap_initiatingmessage_choice_text[msg->choice_type]); + m_s1ap_log->error("Unhandled intiating message: %s\n", liblte_s1ap_initiatingmessage_choice_text[msg->choice_type]); } return true; } bool -s1ap::handle_s1setuprequest(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri) +s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri) { uint8_t enb_name[150]; @@ -184,8 +177,21 @@ s1ap::handle_s1setuprequest(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, stru uint16_t mcc, mnc; uint16_t tac, bplmn; uint32_t bplmns[32]; + enb_ctx_t enb_ctx; + if(!m_s1ap_mngmt_proc.unpack_s1_setup_request(msg, &enb_ctx)){ + m_s1ap_log->error("Malformed S1 Setup Request\n"); + return false; + } + + if(enb_ctx.enb_name_present){ + m_s1ap_log->console("S1 Setup request from eNB %s\n", enb_ctx.enb_name); + } + else{ + m_s1ap_log->console("S1 Setup request from eNB id \n"); + } //eNB Name + /* if(msg->eNBname_present) { bzero(enb_name,sizeof(enb_name)); @@ -233,14 +239,22 @@ s1ap::handle_s1setuprequest(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, stru //Default Paging DRX LIBLTE_S1AP_PAGINGDRX_ENUM drx = msg->DefaultPagingDRX.e; std::cout << "Default Paging DRX" << drx << std::endl; - + */ + /* + if(plmn!=m_plmn){ + send_s1_setup_failure(enb_sri); + } + else{ + send_s1_setup_response(enb_sri); + } + */ //send_s1setupfailure(enb_sri); - send_s1setupresponse(enb_sri); + //send_s1setupresponse(enb_sri); return true; } bool -s1ap::send_s1setupfailure(struct sctp_sndrcvinfo *enb_sri) +s1ap::send_s1_setup_failure(struct sctp_sndrcvinfo *enb_sri) { srslte::byte_buffer_t msg; LIBLTE_S1AP_S1AP_PDU_STRUCT pdu; @@ -276,7 +290,7 @@ s1ap::send_s1setupfailure(struct sctp_sndrcvinfo *enb_sri) bool -s1ap::send_s1setupresponse(struct sctp_sndrcvinfo *enb_sri) +s1ap::send_s1_setup_response(struct sctp_sndrcvinfo *enb_sri) { srslte::byte_buffer_t msg; LIBLTE_S1AP_S1AP_PDU_STRUCT pdu; @@ -340,12 +354,4 @@ s1ap::send_s1setupresponse(struct sctp_sndrcvinfo *enb_sri) return true; } - -/* -bool -s1ap::setup_enb_ctx() -{ - return false; -}*/ - } //namespace srsepc From eb3520630d1d7105ec0cc1db20535c3e53b7eff5 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 19 Oct 2017 19:42:18 +0100 Subject: [PATCH 023/172] Cleanned up the setup request and failure packing/unpacking --- srsepc/src/mme/s1ap.cc | 132 ++++++++++++----------------------------- 1 file changed, 38 insertions(+), 94 deletions(-) diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 5f410c62a..58a2185ce 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -170,125 +170,69 @@ bool s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri) { - uint8_t enb_name[150]; - uint8_t enb_id[20]; - uint32_t plmn = 0; std::string mnc_str, mcc_str; - uint16_t mcc, mnc; - uint16_t tac, bplmn; - uint32_t bplmns[32]; enb_ctx_t enb_ctx; + srslte::byte_buffer_t reply_msg; + LIBLTE_S1AP_S1AP_PDU_STRUCT reply_pdu; - if(!m_s1ap_mngmt_proc.unpack_s1_setup_request(msg, &enb_ctx)){ + if(!m_s1ap_mngmt_proc.unpack_s1_setup_request(msg, &enb_ctx)) + { m_s1ap_log->error("Malformed S1 Setup Request\n"); return false; } - if(enb_ctx.enb_name_present){ - m_s1ap_log->console("S1 Setup request from eNB %s\n", enb_ctx.enb_name); - } - else{ - m_s1ap_log->console("S1 Setup request from eNB id \n"); - } - //eNB Name - /* - if(msg->eNBname_present) + //Log S1 Setup Request Info + if(enb_ctx.enb_name_present) { - bzero(enb_name,sizeof(enb_name)); - memcpy(enb_name,&msg->eNBname.buffer,msg->eNBname.n_octets); - std::cout <<"eNB Name: " << enb_name <console("S1 Setup Request - eNB Name: %s, eNB id: 0x%x\n", enb_ctx.enb_name, enb_ctx.enb_id); + m_s1ap_log->info("S1 Setup Request - eNB Name: %s, eNB id: 0x%x\n", enb_ctx.enb_name, enb_ctx.enb_id); } - //eNB Id 9.2.1.37 - memcpy(&enb_id, msg->Global_ENB_ID.eNB_ID.choice.macroENB_ID.buffer, LIBLTE_S1AP_MACROENB_ID_BIT_STRING_LEN); - std::cout << "eNB ID: "; - for (int i=0;i < 20;i++) { - std::cout<< (uint16_t)enb_id[i]; - } - std::cout << std::endl; - //PLMN Id - ((uint8_t*)&plmn)[1] = msg->Global_ENB_ID.pLMNidentity.buffer[0]; - ((uint8_t*)&plmn)[2] = msg->Global_ENB_ID.pLMNidentity.buffer[1]; - ((uint8_t*)&plmn)[3] = msg->Global_ENB_ID.pLMNidentity.buffer[2]; - - plmn = ntohl(plmn); - srslte::s1ap_plmn_to_mccmnc(plmn, &mcc, &mnc); - srslte::mnc_to_string(mnc, &mnc_str); - srslte::mnc_to_string(mcc, &mcc_str); - std::cout << "MCC: "<< mcc_str << " MNC: " << mnc_str << std::endl; - - //SupportedTAs - for(uint16_t i=0; iSupportedTAs.len; i++) + else { - //tac = msg->SupportedTAs.buffer[i].tAC.buffer[]; //broadcastPLMNs - ((uint8_t*)&tac)[0] = msg->SupportedTAs.buffer[i].tAC.buffer[0]; - ((uint8_t*)&tac)[1] = msg->SupportedTAs.buffer[i].tAC.buffer[1]; - std::cout << "TAC: " << ntohs(tac) << std::endl; - for (uint16_t j=0; jSupportedTAs.buffer[i].broadcastPLMNs.len; j++) + m_s1ap_log->console("S1 Setup Request - eNB Id 0x%x\n", enb_ctx.enb_id); + m_s1ap_log->info("S1 Setup request - eNB Id 0x%x\n", enb_ctx.enb_id); + } + srslte::mcc_to_string(enb_ctx.mcc, &mcc_str); + srslte::mnc_to_string(enb_ctx.mnc, &mnc_str); + m_s1ap_log->info("S1 Setup Request - MCC:%s, MNC:%s, PLMN: %d\n", mcc_str.c_str(), mnc_str.c_str(), enb_ctx.plmn); + m_s1ap_log->console("S1 Setup Request - MCC:%s, MNC:%s, PLMN: %d\n", mcc_str.c_str(), mnc_str.c_str(), enb_ctx.plmn); + for(int i=0;iSupportedTAs.buffer[i].broadcastPLMNs.buffer[j].buffer[0]; - ((uint8_t*)&bplmns[j])[2] = msg->SupportedTAs.buffer[i].broadcastPLMNs.buffer[j].buffer[1]; - ((uint8_t*)&bplmns[j])[3] = msg->SupportedTAs.buffer[i].broadcastPLMNs.buffer[j].buffer[2]; - - bplmns[j] = ntohl(bplmns[j]); - srslte::mnc_to_string(mnc, &mnc_str); - srslte::mnc_to_string(mcc, &mcc_str); - std::cout << "B_MCC: "<< mcc_str << " B_MNC: " << mnc_str << std::endl; + m_s1ap_log->info("S1 Setup Request - TAC %d, B-PLMN %d\n",enb_ctx.tac[i],enb_ctx.bplmns[i][j]); + m_s1ap_log->console("S1 Setup Request - TAC %d, B-PLMN %d\n",enb_ctx.tac[i],enb_ctx.bplmns[i][j]); } - } - - //Default Paging DRX - LIBLTE_S1AP_PAGINGDRX_ENUM drx = msg->DefaultPagingDRX.e; - std::cout << "Default Paging DRX" << drx << std::endl; - */ - /* - if(plmn!=m_plmn){ - send_s1_setup_failure(enb_sri); + } + m_s1ap_log->console("S1 Setup Request - Paging DRX %d\n",enb_ctx.drx); + + //Check matching PLMNs + if(enb_ctx.plmn!=m_plmn){ + m_s1ap_log->console("S1 Setup Failure - Unkown PLMN\n"); + m_s1ap_log->info("S1 Setup Failure - Unkown PLMN\n"); + m_s1ap_mngmt_proc.pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_UNKNOWN_PLMN,&reply_msg); + ssize_t n_sent = sctp_send(m_s1mme,reply_msg.msg, reply_msg.N_bytes, enb_sri, 0); //FIXME } else{ + m_s1ap_log->console("S1 Setup Response\n"); + m_s1ap_log->info("S1 Setup Response\n"); + //m_s1ap_mngmt_proc.pack_s1_setup_response(,&reply_msg); send_s1_setup_response(enb_sri); } - */ - //send_s1setupfailure(enb_sri); - //send_s1setupresponse(enb_sri); - return true; -} - -bool -s1ap::send_s1_setup_failure(struct sctp_sndrcvinfo *enb_sri) -{ - srslte::byte_buffer_t msg; - LIBLTE_S1AP_S1AP_PDU_STRUCT pdu; - bzero(&pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); - - pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_UNSUCCESSFULOUTCOME; - - LIBLTE_S1AP_UNSUCCESSFULOUTCOME_STRUCT *unsucc = &pdu.choice.unsuccessfulOutcome; - unsucc->procedureCode = LIBLTE_S1AP_PROC_ID_S1SETUP; - unsucc->criticality = LIBLTE_S1AP_CRITICALITY_REJECT; - unsucc->choice_type = LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_S1SETUPFAILURE; - - LIBLTE_S1AP_MESSAGE_S1SETUPFAILURE_STRUCT* s1_fail=(LIBLTE_S1AP_MESSAGE_S1SETUPFAILURE_STRUCT*)&unsucc->choice; - - s1_fail->TimeToWait_present=false; - s1_fail->CriticalityDiagnostics_present=false; - s1_fail->Cause.ext=false; - s1_fail->Cause.choice_type = LIBLTE_S1AP_CAUSE_CHOICE_MISC; - s1_fail->Cause.choice.misc.ext=false; - s1_fail->Cause.choice.misc.e=LIBLTE_S1AP_CAUSEMISC_UNKNOWN_PLMN; - - liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)&msg); + //Send Reply to eNB + /* ssize_t n_sent = sctp_send(m_s1mme,msg.msg, msg.N_bytes, enb_sri, 0); - if(n_sent == -1) { - m_s1ap_log->console("Failed to send S1 Setup Failure"); + m_s1ap_log->console("Failed to send S1 Setup Setup Reply"); return false; } + */ return true; + } - bool s1ap::send_s1_setup_response(struct sctp_sndrcvinfo *enb_sri) { From f73d295ae01a099d61452def1be08b947ff7ba0b Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 20 Oct 2017 09:35:26 +0100 Subject: [PATCH 024/172] Separating msg packing from the main S1AP class. --- srsepc/hdr/mme/s1ap_mngmt_proc.h | 63 ++++++++++ srsepc/src/mme/s1ap_mngmt_proc.cc | 184 ++++++++++++++++++++++++++++++ 2 files changed, 247 insertions(+) create mode 100644 srsepc/hdr/mme/s1ap_mngmt_proc.h create mode 100644 srsepc/src/mme/s1ap_mngmt_proc.cc diff --git a/srsepc/hdr/mme/s1ap_mngmt_proc.h b/srsepc/hdr/mme/s1ap_mngmt_proc.h new file mode 100644 index 000000000..c70c918bc --- /dev/null +++ b/srsepc/hdr/mme/s1ap_mngmt_proc.h @@ -0,0 +1,63 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ +#ifndef S1AP_MNGMT_PROC_H +#define S1AP_MNGMT_PROC_H + +#include "srslte/asn1/liblte_s1ap.h" +#include "srslte/common/common.h" +namespace srsepc{ + +static const uint8_t MAX_TA=255; +static const uint8_t MAX_BPLMN=6; + +typedef struct{ + bool enb_name_present; + uint32_t enb_id; + uint8_t enb_name[150]; + uint16_t mcc, mnc; + uint32_t plmn; + uint8_t nof_supported_ta; + uint16_t tac[MAX_TA]; + uint8_t nof_supported_bplmns[MAX_TA]; + uint16_t bplmns[MAX_TA][MAX_BPLMN]; + LIBLTE_S1AP_PAGINGDRX_ENUM drx; + struct sctp_sndrcvinfo sri; +} enb_ctx_t; + +class s1ap_mngmt_proc +{ +public: + s1ap_mngmt_proc(); + virtual ~s1ap_mngmt_proc(); + + bool unpack_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, enb_ctx_t* enb_ctx); + bool pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_ENUM cause, srslte::byte_buffer_t* msg); + bool pack_s1_setup_response(LIBLTE_S1AP_S1AP_PDU_STRUCT *pdu); +}; + +} //namespace srsepc + +#endif //S1AP_MNGMT_PROC diff --git a/srsepc/src/mme/s1ap_mngmt_proc.cc b/srsepc/src/mme/s1ap_mngmt_proc.cc new file mode 100644 index 000000000..be66399cc --- /dev/null +++ b/srsepc/src/mme/s1ap_mngmt_proc.cc @@ -0,0 +1,184 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +//#include "srslte/upper/s1ap_common.h" +#include "srslte/common/bcd_helpers.h" +#include "mme/s1ap.h" +#include "mme/s1ap_mngmt_proc.h" + +namespace srsepc{ + +s1ap_mngmt_proc::s1ap_mngmt_proc() +{ +} + +s1ap_mngmt_proc::~s1ap_mngmt_proc() +{ +} + +bool +s1ap_mngmt_proc::unpack_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, enb_ctx_t* enb_ctx) +{ + + uint8_t enb_id_bits[32]; + uint32_t plmn = 0; + uint16_t tac, bplmn; + + uint32_t tmp32=0; + //eNB Name + enb_ctx->enb_name_present=msg->eNBname_present; + if(msg->eNBname_present) + { + bzero(enb_ctx->enb_name,sizeof(enb_ctx->enb_name)); + memcpy(enb_ctx->enb_name,&msg->eNBname.buffer,msg->eNBname.n_octets); + } + //eNB Id + bzero(enb_id_bits,sizeof(enb_id_bits)); + memcpy(&enb_id_bits[32-LIBLTE_S1AP_MACROENB_ID_BIT_STRING_LEN], msg->Global_ENB_ID.eNB_ID.choice.macroENB_ID.buffer, LIBLTE_S1AP_MACROENB_ID_BIT_STRING_LEN); + liblte_pack(enb_id_bits, 32, (uint8_t*) &tmp32); + enb_ctx->enb_id=ntohl(tmp32); + + //PLMN Id + ((uint8_t*)&plmn)[1] = msg->Global_ENB_ID.pLMNidentity.buffer[0]; + ((uint8_t*)&plmn)[2] = msg->Global_ENB_ID.pLMNidentity.buffer[1]; + ((uint8_t*)&plmn)[3] = msg->Global_ENB_ID.pLMNidentity.buffer[2]; + + enb_ctx->plmn = ntohl(plmn); + srslte::s1ap_plmn_to_mccmnc(enb_ctx->plmn, &enb_ctx->mcc, &enb_ctx->mnc); + + //SupportedTAs + enb_ctx->nof_supported_ta=msg->SupportedTAs.len; + for(uint16_t i=0; iSupportedTAs.len; i++) + { + //TAC + ((uint8_t*)&enb_ctx->tac[i])[0] = msg->SupportedTAs.buffer[i].tAC.buffer[0]; + ((uint8_t*)&enb_ctx->tac[i])[1] = msg->SupportedTAs.buffer[i].tAC.buffer[1]; + enb_ctx->tac[i]=ntohs(enb_ctx->tac[i]); + enb_ctx->nof_supported_bplmns[i]=msg->SupportedTAs.buffer[i].broadcastPLMNs.len; + for (uint16_t j=0; jSupportedTAs.buffer[i].broadcastPLMNs.len; j++) + { + //BPLMNs + ((uint8_t*)&enb_ctx->bplmns[i][j])[1] = msg->SupportedTAs.buffer[i].broadcastPLMNs.buffer[j].buffer[0]; + ((uint8_t*)&enb_ctx->bplmns[i][j])[2] = msg->SupportedTAs.buffer[i].broadcastPLMNs.buffer[j].buffer[1]; + ((uint8_t*)&enb_ctx->bplmns[i][j])[3] = msg->SupportedTAs.buffer[i].broadcastPLMNs.buffer[j].buffer[2]; + + enb_ctx->bplmns[i][j] = ntohl(enb_ctx->bplmns[i][j]); + } + } + + //Default Paging DRX + enb_ctx->drx = msg->DefaultPagingDRX.e; + + return true; +} + +bool +s1ap_mngmt_proc::pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_ENUM cause, srslte::byte_buffer_t *msg) +{ + LIBLTE_S1AP_S1AP_PDU_STRUCT pdu; + bzero(&pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); + + pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_UNSUCCESSFULOUTCOME; + + LIBLTE_S1AP_UNSUCCESSFULOUTCOME_STRUCT *unsucc = &pdu.choice.unsuccessfulOutcome; + unsucc->procedureCode = LIBLTE_S1AP_PROC_ID_S1SETUP; + unsucc->criticality = LIBLTE_S1AP_CRITICALITY_REJECT; + unsucc->choice_type = LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_S1SETUPFAILURE; + + LIBLTE_S1AP_MESSAGE_S1SETUPFAILURE_STRUCT* s1_fail=(LIBLTE_S1AP_MESSAGE_S1SETUPFAILURE_STRUCT*)&unsucc->choice; + + s1_fail->TimeToWait_present=false; + s1_fail->CriticalityDiagnostics_present=false; + s1_fail->Cause.ext=false; + s1_fail->Cause.choice_type = LIBLTE_S1AP_CAUSE_CHOICE_MISC; + s1_fail->Cause.choice.misc.ext=false; + s1_fail->Cause.choice.misc.e=cause; + + liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)msg); + return true; + } + + +bool +s1ap_mngmt_proc::pack_s1_setup_response(LIBLTE_S1AP_S1AP_PDU_STRUCT *pdu) +{ +/* + srslte::byte_buffer_t msg; + //LIBLTE_S1AP_S1AP_PDU_STRUCT pdu; + bzero(pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); + + pdu->choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME; + + LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *succ = &pdu->choice.successfulOutcome; + succ->procedureCode = LIBLTE_S1AP_PROC_ID_S1SETUP; + succ->criticality = LIBLTE_S1AP_CRITICALITY_IGNORE; + succ->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_S1SETUPRESPONSE; + + LIBLTE_S1AP_MESSAGE_S1SETUPRESPONSE_STRUCT* s1_resp=(LIBLTE_S1AP_MESSAGE_S1SETUPRESPONSE_STRUCT*)&succ->choice; + + s1_resp->ext=false; + + //MME Name + s1_resp->MMEname_present=true; + s1_resp->MMEname.ext=false; + s1_resp->MMEname.n_octets=m_mme_name.length(); + memcpy(s1_resp->MMEname.buffer,m_mme_name.c_str(),m_mme_name.length()); + + //Served GUMEIs + s1_resp->ServedGUMMEIs.len=1;//TODO Only one served GUMMEI supported + LIBLTE_S1AP_SERVEDGUMMEISITEM_STRUCT *serv_gummei = &s1_resp->ServedGUMMEIs.buffer[0]; + + serv_gummei->ext=false; + //serv_gummei->iE_Extensions=false; + + uint32_t plmn=0; + srslte::s1ap_mccmnc_to_plmn(m_mcc, m_mnc, &plmn); + plmn=htonl(plmn); + serv_gummei->servedPLMNs.len = 1; //Only one PLMN supported + serv_gummei->servedPLMNs.buffer[0].buffer[0]=((uint8_t*)&plmn)[1]; + serv_gummei->servedPLMNs.buffer[0].buffer[1]=((uint8_t*)&plmn)[2]; + serv_gummei->servedPLMNs.buffer[0].buffer[2]=((uint8_t*)&plmn)[3]; + + serv_gummei->servedGroupIDs.len=1; //LIBLTE_S1AP_SERVEDGROUPIDS_STRUCT + uint16_t tmp=htons(m_mme_group); + serv_gummei->servedGroupIDs.buffer[0].buffer[0]=((uint8_t*)&tmp)[0]; + serv_gummei->servedGroupIDs.buffer[0].buffer[1]=((uint8_t*)&tmp)[1]; + + serv_gummei->servedMMECs.len=1; //Only one MMEC served + serv_gummei->servedMMECs.buffer[0].buffer[0]=m_mme_code; + + //Relative MME Capacity + s1_resp->RelativeMMECapacity.RelativeMMECapacity=255; + + //Relay Unsupported + s1_resp->MMERelaySupportIndicator_present=false; + + liblte_s1ap_pack_s1ap_pdu(pdu, (LIBLTE_BYTE_MSG_STRUCT*)&msg); +*/ + return true; +} + +} //namespace srsepc From 0dbddb8a4bf2f42f93a0ef63a19997a8c6d113aa Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 20 Oct 2017 11:45:45 +0100 Subject: [PATCH 025/172] Finished separating the pack/unpack from the main S1AP class. --- srsepc/hdr/mme/s1ap.h | 21 ++--- srsepc/hdr/mme/s1ap_mngmt_proc.h | 21 +---- srsepc/src/mme/s1ap.cc | 132 +++++++++--------------------- srsepc/src/mme/s1ap_mngmt_proc.cc | 27 +++--- 4 files changed, 63 insertions(+), 138 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 9b3c546c6..d8e347661 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -37,22 +37,13 @@ #include #include +#include "mme/s1ap_common.h" #include "mme/s1ap_mngmt_proc.h" namespace srsepc{ const uint16_t S1MME_PORT = 36412; -typedef struct{ - uint8_t mme_code; - uint16_t mme_group; - uint16_t tac; // 16-bit tac - uint16_t mcc; // BCD-coded with 0xF filler - uint16_t mnc; // BCD-coded with 0xF filler - std::string mme_bind_addr; - std::string mme_name; -} s1ap_args_t; - class s1ap { public: @@ -73,18 +64,24 @@ public: bool send_s1_setup_failure(struct sctp_sndrcvinfo *enb_sri); bool send_s1_setup_response(struct sctp_sndrcvinfo *enb_sri); + + void print_enb_ctx_info(const enb_ctx_t &enb_ctx); private: + + s1ap_args_t m_s1ap_args; + uint32_t m_plmn; + /* uint8_t m_mme_code; uint16_t m_mme_group; uint16_t m_tac; // 16-bit tac uint16_t m_mcc; // BCD-coded with 0xF filler uint16_t m_mnc; // BCD-coded with 0xF filler uint32_t m_plmn; - + std::string m_mme_bind_addr; std::string m_mme_name; - + */ srslte::log *m_s1ap_log; int m_s1mme; diff --git a/srsepc/hdr/mme/s1ap_mngmt_proc.h b/srsepc/hdr/mme/s1ap_mngmt_proc.h index c70c918bc..53c74f9eb 100644 --- a/srsepc/hdr/mme/s1ap_mngmt_proc.h +++ b/srsepc/hdr/mme/s1ap_mngmt_proc.h @@ -28,25 +28,10 @@ #include "srslte/asn1/liblte_s1ap.h" #include "srslte/common/common.h" +#include "mme/s1ap_common.h" + namespace srsepc{ -static const uint8_t MAX_TA=255; -static const uint8_t MAX_BPLMN=6; - -typedef struct{ - bool enb_name_present; - uint32_t enb_id; - uint8_t enb_name[150]; - uint16_t mcc, mnc; - uint32_t plmn; - uint8_t nof_supported_ta; - uint16_t tac[MAX_TA]; - uint8_t nof_supported_bplmns[MAX_TA]; - uint16_t bplmns[MAX_TA][MAX_BPLMN]; - LIBLTE_S1AP_PAGINGDRX_ENUM drx; - struct sctp_sndrcvinfo sri; -} enb_ctx_t; - class s1ap_mngmt_proc { public: @@ -55,7 +40,7 @@ public: bool unpack_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, enb_ctx_t* enb_ctx); bool pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_ENUM cause, srslte::byte_buffer_t* msg); - bool pack_s1_setup_response(LIBLTE_S1AP_S1AP_PDU_STRUCT *pdu); + bool pack_s1_setup_response(s1ap_args_t s1ap_args, srslte::byte_buffer_t* msg); }; } //namespace srsepc diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 58a2185ce..765a0646e 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -43,6 +43,7 @@ s1ap::~s1ap() int s1ap::init(s1ap_args_t s1ap_args, srslte::log *s1ap_log) { + /* m_mme_code = s1ap_args.mme_code ; m_mme_group = s1ap_args.mme_group; m_tac = s1ap_args.tac; @@ -50,8 +51,10 @@ s1ap::init(s1ap_args_t s1ap_args, srslte::log *s1ap_log) m_mnc = s1ap_args.mnc; m_mme_bind_addr = s1ap_args.mme_bind_addr; m_mme_name = std::string("srsmme0"); + */ + m_s1ap_args = s1ap_args; - srslte::s1ap_mccmnc_to_plmn(m_mcc, m_mnc, &m_plmn); + srslte::s1ap_mccmnc_to_plmn(s1ap_args.mcc, s1ap_args.mnc, &m_plmn); m_s1ap_log = s1ap_log; @@ -101,7 +104,7 @@ s1ap::enb_listen() //S1-MME bind bzero(&s1mme_addr, sizeof(s1mme_addr)); s1mme_addr.sin_family = AF_INET; - inet_pton(AF_INET, m_mme_bind_addr.c_str(), &(s1mme_addr.sin_addr) ); + inet_pton(AF_INET, m_s1ap_args.mme_bind_addr.c_str(), &(s1mme_addr.sin_addr) ); s1mme_addr.sin_port = htons(S1MME_PORT); err = bind(sock_fd, (struct sockaddr*) &s1mme_addr, sizeof (s1mme_addr)); if (err != 0){ @@ -182,6 +185,37 @@ s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, st } //Log S1 Setup Request Info + print_enb_ctx_info(enb_ctx); + + //Check matching PLMNs + if(enb_ctx.plmn!=m_plmn){ + m_s1ap_log->console("S1 Setup Failure - Unkown PLMN\n"); + m_s1ap_log->info("S1 Setup Failure - Unkown PLMN\n"); + m_s1ap_mngmt_proc.pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_UNKNOWN_PLMN,&reply_msg); + } + else{ + m_s1ap_log->console("S1 Setup Response\n"); + m_s1ap_log->info("S1 Setup Response\n"); + m_s1ap_mngmt_proc.pack_s1_setup_response(m_s1ap_args, &reply_msg); + } + + //Send Reply to eNB + ssize_t n_sent = sctp_send(m_s1mme,reply_msg.msg, reply_msg.N_bytes, enb_sri, 0); + if(n_sent == -1) + { + m_s1ap_log->console("Failed to send S1 Setup Setup Reply"); + return false; + } + + return true; + +} + +void +s1ap::print_enb_ctx_info(const enb_ctx_t &enb_ctx) +{ + std::string mnc_str, mcc_str; + if(enb_ctx.enb_name_present) { m_s1ap_log->console("S1 Setup Request - eNB Name: %s, eNB id: 0x%x\n", enb_ctx.enb_name, enb_ctx.enb_id); @@ -203,99 +237,9 @@ s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, st m_s1ap_log->info("S1 Setup Request - TAC %d, B-PLMN %d\n",enb_ctx.tac[i],enb_ctx.bplmns[i][j]); m_s1ap_log->console("S1 Setup Request - TAC %d, B-PLMN %d\n",enb_ctx.tac[i],enb_ctx.bplmns[i][j]); } - } + } m_s1ap_log->console("S1 Setup Request - Paging DRX %d\n",enb_ctx.drx); - - //Check matching PLMNs - if(enb_ctx.plmn!=m_plmn){ - m_s1ap_log->console("S1 Setup Failure - Unkown PLMN\n"); - m_s1ap_log->info("S1 Setup Failure - Unkown PLMN\n"); - m_s1ap_mngmt_proc.pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_UNKNOWN_PLMN,&reply_msg); - ssize_t n_sent = sctp_send(m_s1mme,reply_msg.msg, reply_msg.N_bytes, enb_sri, 0); //FIXME - } - else{ - m_s1ap_log->console("S1 Setup Response\n"); - m_s1ap_log->info("S1 Setup Response\n"); - //m_s1ap_mngmt_proc.pack_s1_setup_response(,&reply_msg); - send_s1_setup_response(enb_sri); - } - - //Send Reply to eNB - /* - ssize_t n_sent = sctp_send(m_s1mme,msg.msg, msg.N_bytes, enb_sri, 0); - if(n_sent == -1) - { - m_s1ap_log->console("Failed to send S1 Setup Setup Reply"); - return false; - } - */ - return true; - -} - -bool -s1ap::send_s1_setup_response(struct sctp_sndrcvinfo *enb_sri) -{ - srslte::byte_buffer_t msg; - LIBLTE_S1AP_S1AP_PDU_STRUCT pdu; - bzero(&pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); - - pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME; - - LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *succ = &pdu.choice.successfulOutcome; - succ->procedureCode = LIBLTE_S1AP_PROC_ID_S1SETUP; - succ->criticality = LIBLTE_S1AP_CRITICALITY_IGNORE; - succ->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_S1SETUPRESPONSE; - - LIBLTE_S1AP_MESSAGE_S1SETUPRESPONSE_STRUCT* s1_resp=(LIBLTE_S1AP_MESSAGE_S1SETUPRESPONSE_STRUCT*)&succ->choice; - - s1_resp->ext=false; - - //MME Name - s1_resp->MMEname_present=true; - s1_resp->MMEname.ext=false; - s1_resp->MMEname.n_octets=m_mme_name.length(); - memcpy(s1_resp->MMEname.buffer,m_mme_name.c_str(),m_mme_name.length()); - - //Served GUMEIs - s1_resp->ServedGUMMEIs.len=1;//TODO Only one served GUMMEI supported - LIBLTE_S1AP_SERVEDGUMMEISITEM_STRUCT *serv_gummei = &s1_resp->ServedGUMMEIs.buffer[0]; - - serv_gummei->ext=false; - //serv_gummei->iE_Extensions=false; - - uint32_t plmn=0; - srslte::s1ap_mccmnc_to_plmn(m_mcc, m_mnc, &plmn); - plmn=htonl(plmn); - serv_gummei->servedPLMNs.len = 1; //Only one PLMN supported - serv_gummei->servedPLMNs.buffer[0].buffer[0]=((uint8_t*)&plmn)[1]; - serv_gummei->servedPLMNs.buffer[0].buffer[1]=((uint8_t*)&plmn)[2]; - serv_gummei->servedPLMNs.buffer[0].buffer[2]=((uint8_t*)&plmn)[3]; - - serv_gummei->servedGroupIDs.len=1; //LIBLTE_S1AP_SERVEDGROUPIDS_STRUCT - uint16_t tmp=htons(m_mme_group); - serv_gummei->servedGroupIDs.buffer[0].buffer[0]=((uint8_t*)&tmp)[0]; - serv_gummei->servedGroupIDs.buffer[0].buffer[1]=((uint8_t*)&tmp)[1]; - - serv_gummei->servedMMECs.len=1; //Only one MMEC served - serv_gummei->servedMMECs.buffer[0].buffer[0]=m_mme_code; - - //Relative MME Capacity - s1_resp->RelativeMMECapacity.RelativeMMECapacity=255; - - //Relay Unsupported - s1_resp->MMERelaySupportIndicator_present=false; - - liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)&msg); - - ssize_t n_sent = sctp_send(m_s1mme,msg.msg, msg.N_bytes, enb_sri, 0); - - if(n_sent == -1) - { - m_s1ap_log->console("Failed to send S1 Setup Failure"); - return false; - } - return true; + return; } } //namespace srsepc diff --git a/srsepc/src/mme/s1ap_mngmt_proc.cc b/srsepc/src/mme/s1ap_mngmt_proc.cc index be66399cc..3a4768bc1 100644 --- a/srsepc/src/mme/s1ap_mngmt_proc.cc +++ b/srsepc/src/mme/s1ap_mngmt_proc.cc @@ -123,16 +123,15 @@ s1ap_mngmt_proc::pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_ENUM cause, srslte: bool -s1ap_mngmt_proc::pack_s1_setup_response(LIBLTE_S1AP_S1AP_PDU_STRUCT *pdu) +s1ap_mngmt_proc::pack_s1_setup_response(s1ap_args_t s1ap_args, srslte::byte_buffer_t *msg) { -/* - srslte::byte_buffer_t msg; - //LIBLTE_S1AP_S1AP_PDU_STRUCT pdu; - bzero(pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); - pdu->choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME; + LIBLTE_S1AP_S1AP_PDU_STRUCT pdu; + bzero(&pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); - LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *succ = &pdu->choice.successfulOutcome; + pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME; + + LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *succ = &pdu.choice.successfulOutcome; succ->procedureCode = LIBLTE_S1AP_PROC_ID_S1SETUP; succ->criticality = LIBLTE_S1AP_CRITICALITY_IGNORE; succ->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_S1SETUPRESPONSE; @@ -144,8 +143,8 @@ s1ap_mngmt_proc::pack_s1_setup_response(LIBLTE_S1AP_S1AP_PDU_STRUCT *pdu) //MME Name s1_resp->MMEname_present=true; s1_resp->MMEname.ext=false; - s1_resp->MMEname.n_octets=m_mme_name.length(); - memcpy(s1_resp->MMEname.buffer,m_mme_name.c_str(),m_mme_name.length()); + s1_resp->MMEname.n_octets=s1ap_args.mme_name.length(); + memcpy(s1_resp->MMEname.buffer,s1ap_args.mme_name.c_str(),s1ap_args.mme_name.length()); //Served GUMEIs s1_resp->ServedGUMMEIs.len=1;//TODO Only one served GUMMEI supported @@ -155,7 +154,7 @@ s1ap_mngmt_proc::pack_s1_setup_response(LIBLTE_S1AP_S1AP_PDU_STRUCT *pdu) //serv_gummei->iE_Extensions=false; uint32_t plmn=0; - srslte::s1ap_mccmnc_to_plmn(m_mcc, m_mnc, &plmn); + srslte::s1ap_mccmnc_to_plmn(s1ap_args.mcc, s1ap_args.mnc, &plmn); plmn=htonl(plmn); serv_gummei->servedPLMNs.len = 1; //Only one PLMN supported serv_gummei->servedPLMNs.buffer[0].buffer[0]=((uint8_t*)&plmn)[1]; @@ -163,12 +162,12 @@ s1ap_mngmt_proc::pack_s1_setup_response(LIBLTE_S1AP_S1AP_PDU_STRUCT *pdu) serv_gummei->servedPLMNs.buffer[0].buffer[2]=((uint8_t*)&plmn)[3]; serv_gummei->servedGroupIDs.len=1; //LIBLTE_S1AP_SERVEDGROUPIDS_STRUCT - uint16_t tmp=htons(m_mme_group); + uint16_t tmp=htons(s1ap_args.mme_group); serv_gummei->servedGroupIDs.buffer[0].buffer[0]=((uint8_t*)&tmp)[0]; serv_gummei->servedGroupIDs.buffer[0].buffer[1]=((uint8_t*)&tmp)[1]; serv_gummei->servedMMECs.len=1; //Only one MMEC served - serv_gummei->servedMMECs.buffer[0].buffer[0]=m_mme_code; + serv_gummei->servedMMECs.buffer[0].buffer[0]=s1ap_args.mme_code; //Relative MME Capacity s1_resp->RelativeMMECapacity.RelativeMMECapacity=255; @@ -176,8 +175,8 @@ s1ap_mngmt_proc::pack_s1_setup_response(LIBLTE_S1AP_S1AP_PDU_STRUCT *pdu) //Relay Unsupported s1_resp->MMERelaySupportIndicator_present=false; - liblte_s1ap_pack_s1ap_pdu(pdu, (LIBLTE_BYTE_MSG_STRUCT*)&msg); -*/ + liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)msg); + return true; } From bfb7f12298b3c159e1814f1aa92efe1769d96d9a Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 20 Oct 2017 14:16:19 +0100 Subject: [PATCH 026/172] Fixed small bug with sleep. --- srsepc/hdr/mme/s1ap.h | 15 +++------------ srsepc/src/main.cc | 2 +- srsepc/src/mme/mme.cc | 6 ------ srsepc/src/mme/s1ap.cc | 26 ++++++++++++++------------ 4 files changed, 18 insertions(+), 31 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index d8e347661..6052ba3a1 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -36,7 +36,7 @@ #include #include #include - +#include #include "mme/s1ap_common.h" #include "mme/s1ap_mngmt_proc.h" @@ -71,20 +71,11 @@ private: s1ap_args_t m_s1ap_args; uint32_t m_plmn; - /* - uint8_t m_mme_code; - uint16_t m_mme_group; - uint16_t m_tac; // 16-bit tac - uint16_t m_mcc; // BCD-coded with 0xF filler - uint16_t m_mnc; // BCD-coded with 0xF filler - uint32_t m_plmn; - - std::string m_mme_bind_addr; - std::string m_mme_name; - */ srslte::log *m_s1ap_log; int m_s1mme; + std::map m_active_enbs; + s1ap_mngmt_proc m_s1ap_mngmt_proc; }; diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index 4920519dc..078a2c7c7 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -149,7 +149,7 @@ main (int argc,char * argv[] ) mme->start(); while(running) { - sleep(0.5); + sleep(1); } mme->stop(); diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index cdea2f170..6e3a23238 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -106,12 +106,6 @@ mme::stop() return; } -int -mme::get_s1_mme() -{ - return m_s1ap.get_s1_mme(); -} - void mme::run_thread() { diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 765a0646e..51e7412cd 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -24,8 +24,6 @@ * */ -#include //TODO Remove - #include "srslte/common/bcd_helpers.h" #include "mme/s1ap.h" @@ -43,15 +41,7 @@ s1ap::~s1ap() int s1ap::init(s1ap_args_t s1ap_args, srslte::log *s1ap_log) { - /* - m_mme_code = s1ap_args.mme_code ; - m_mme_group = s1ap_args.mme_group; - m_tac = s1ap_args.tac; - m_mcc = s1ap_args.mcc; - m_mnc = s1ap_args.mnc; - m_mme_bind_addr = s1ap_args.mme_bind_addr; - m_mme_name = std::string("srsmme0"); - */ + m_s1ap_args = s1ap_args; srslte::s1ap_mccmnc_to_plmn(s1ap_args.mcc, s1ap_args.mnc, &m_plmn); @@ -194,9 +184,21 @@ s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, st m_s1ap_mngmt_proc.pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_UNKNOWN_PLMN,&reply_msg); } else{ + /* + if(m_active_enbs.find(enb_ctx.enb_id)) + { + //eNB already registered + } + else + { + //new eNB + + } + */ + m_active_enbs.insert(std::pair(enb_ctx.enb_id,enb_ctx)); + m_s1ap_mngmt_proc.pack_s1_setup_response(m_s1ap_args, &reply_msg); m_s1ap_log->console("S1 Setup Response\n"); m_s1ap_log->info("S1 Setup Response\n"); - m_s1ap_mngmt_proc.pack_s1_setup_response(m_s1ap_args, &reply_msg); } //Send Reply to eNB From 17ffc1f4bb91a2e6eda30875d36b83655ff6dab5 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 20 Oct 2017 14:21:23 +0100 Subject: [PATCH 027/172] Added a file for common S1AP structs --- srsepc/hdr/mme/s1ap_common.h | 51 ++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 srsepc/hdr/mme/s1ap_common.h diff --git a/srsepc/hdr/mme/s1ap_common.h b/srsepc/hdr/mme/s1ap_common.h new file mode 100644 index 000000000..4d76570f9 --- /dev/null +++ b/srsepc/hdr/mme/s1ap_common.h @@ -0,0 +1,51 @@ +/* + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ +#ifndef S1AP_COMMON_H +#define S1AP_COMMON_H + +static const uint8_t MAX_TA=255; //Maximum TA supported +static const uint8_t MAX_BPLMN=6; //Maximum broadcasted PLMNs per TAC + +typedef struct{ + uint8_t mme_code; + uint16_t mme_group; + uint16_t tac; // 16-bit tac + uint16_t mcc; // BCD-coded with 0xF filler + uint16_t mnc; // BCD-coded with 0xF filler + std::string mme_bind_addr; + std::string mme_name; +} s1ap_args_t; + +typedef struct{ + bool enb_name_present; + uint32_t enb_id; + uint8_t enb_name[150]; + uint16_t mcc, mnc; + uint32_t plmn; + uint8_t nof_supported_ta; + uint16_t tac[MAX_TA]; + uint8_t nof_supported_bplmns[MAX_TA]; + uint16_t bplmns[MAX_TA][MAX_BPLMN]; + LIBLTE_S1AP_PAGINGDRX_ENUM drx; + struct sctp_sndrcvinfo sri; +} enb_ctx_t; + +#endif From 841f38fac0c2a3e759a76c6c5e5962ef5807ecb9 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 20 Oct 2017 15:21:44 +0100 Subject: [PATCH 028/172] Starting to save eNB context --- srsepc/hdr/mme/s1ap.h | 2 +- srsepc/src/mme/s1ap.cc | 20 +++++++++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 6052ba3a1..4280cf622 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -74,7 +74,7 @@ private: srslte::log *m_s1ap_log; int m_s1mme; - std::map m_active_enbs; + std::map m_active_enbs; s1ap_mngmt_proc m_s1ap_mngmt_proc; }; diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 51e7412cd..91ececbc7 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -59,6 +59,13 @@ s1ap::stop() if (m_s1mme != -1){ close(m_s1mme); } + std::map::iterator it = m_active_enbs.begin(); + while(it!=m_active_enbs.end()) + { + print_enb_ctx_info(*it->second); + delete it->second; + m_active_enbs.erase(it++); + } return; } @@ -184,18 +191,21 @@ s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, st m_s1ap_mngmt_proc.pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_UNKNOWN_PLMN,&reply_msg); } else{ - /* - if(m_active_enbs.find(enb_ctx.enb_id)) + std::map::iterator it = m_active_enbs.find(enb_ctx.enb_id); + if(it != m_active_enbs.end()) { //eNB already registered + //TODO replace enb_ctx } else { //new eNB - + enb_ctx_t *enb_ptr = new enb_ctx_t;//TODO use buffer pool here? + memcpy(enb_ptr,&enb_ctx,sizeof(enb_ctx)); + m_active_enbs.insert(std::pair(enb_ptr->enb_id,enb_ptr)); } - */ - m_active_enbs.insert(std::pair(enb_ctx.enb_id,enb_ctx)); + + //m_active_enbs.insert(std::pair(enb_ctx.enb_id,enb_ctx)); m_s1ap_mngmt_proc.pack_s1_setup_response(m_s1ap_args, &reply_msg); m_s1ap_log->console("S1 Setup Response\n"); m_s1ap_log->info("S1 Setup Response\n"); From b9aff650a7e05f8cde5b178314fc8b81e8509918 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 20 Oct 2017 15:39:23 +0100 Subject: [PATCH 029/172] Storing eNB ctx info --- srsepc/src/mme/mme.cc | 2 +- srsepc/src/mme/s1ap.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index 6e3a23238..65fa1a922 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -98,11 +98,11 @@ mme::stop() { if(m_running) { + m_s1ap.stop(); m_running = false; thread_cancel(); wait_thread_finish(); } - m_s1ap.stop(); return; } diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 91ececbc7..4abbd5dc4 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -62,7 +62,7 @@ s1ap::stop() std::map::iterator it = m_active_enbs.begin(); while(it!=m_active_enbs.end()) { - print_enb_ctx_info(*it->second); + //print_enb_ctx_info(*it->second); delete it->second; m_active_enbs.erase(it++); } From bc447a32fe47c49da94d35f1e1df43b0aad89dd8 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 20 Oct 2017 17:05:52 +0100 Subject: [PATCH 030/172] Addind the mechanisms to cleanup eNB when SCTP connection is terminated. --- srsepc/src/mme/mme.cc | 19 ++++++++++++++++--- srsepc/src/mme/s1ap.cc | 4 +++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index 65fa1a922..ebab43e1e 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -136,9 +136,22 @@ mme::run_thread() m_s1ap_log.debug("Socket timeout reached"); } else{ - pdu->N_bytes = rd_sz; - m_s1ap_log.info("Received S1AP msg. Size: %d\n", pdu->N_bytes); - m_s1ap.handle_s1ap_rx_pdu(pdu,&sri); + if(msg_flags & MSG_NOTIFICATION) + { + //Received notification + m_s1ap_log.console("SCTP Notification %d\n", ((union sctp_notification*)pdu->msg)->sn_header.sn_type); + if (((union sctp_notification*)pdu->msg)->sn_header.sn_type == SCTP_SHUTDOWN_EVENT) + { + m_s1ap_log.console("SCTP Association Gracefully Shutdown\n"); + } + } + else + { + //Received data + pdu->N_bytes = rd_sz; + m_s1ap_log.info("Received S1AP msg. Size: %d\n", pdu->N_bytes); + m_s1ap.handle_s1ap_rx_pdu(pdu,&sri); + } } } return; diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 4abbd5dc4..6fa3382b2 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -62,7 +62,7 @@ s1ap::stop() std::map::iterator it = m_active_enbs.begin(); while(it!=m_active_enbs.end()) { - //print_enb_ctx_info(*it->second); + print_enb_ctx_info(*it->second); delete it->second; m_active_enbs.erase(it++); } @@ -91,8 +91,10 @@ s1ap::enb_listen() } //Sets the data_io_event to be able to use sendrecv_info + //Subscribes to the SCTP_SHUTDOWN event, to handle graceful shutdown bzero (&evnts, sizeof (evnts)) ; evnts.sctp_data_io_event = 1; + evnts.sctp_shutdown_event=1; if(setsockopt(sock_fd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof (evnts))){ m_s1ap_log->console("Subscribing to sctp_data_io_events failed\n"); return -1; From 79c0daea91718f0d17d052d591183d5e3c63ca5b Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 24 Oct 2017 18:08:23 +0100 Subject: [PATCH 031/172] Starting to handle Initial UE message --- srsepc/src/mme/mme.cc | 2 +- srsepc/src/mme/s1ap.cc | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index ebab43e1e..0648c6d4e 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -142,7 +142,7 @@ mme::run_thread() m_s1ap_log.console("SCTP Notification %d\n", ((union sctp_notification*)pdu->msg)->sn_header.sn_type); if (((union sctp_notification*)pdu->msg)->sn_header.sn_type == SCTP_SHUTDOWN_EVENT) { - m_s1ap_log.console("SCTP Association Gracefully Shutdown\n"); + m_s1ap_log.console("SCTP Association Gracefully Shutdown\n");//TODO } } else diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 6fa3382b2..7b2074031 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -162,6 +162,9 @@ s1ap::handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, stru case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_S1SETUPREQUEST: m_s1ap_log->info("Received S1 Setup Request.\n"); return handle_s1_setup_request(&msg->choice.S1SetupRequest, enb_sri); + case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_INITIALUEMESSAGE: + m_s1ap_log->info("Received Initial UE Message.\n"); + return handle_initial_ue_message(&msg->choice.InitialUEMessage, enb_sri); default: m_s1ap_log->error("Unhandled intiating message: %s\n", liblte_s1ap_initiatingmessage_choice_text[msg->choice_type]); } @@ -225,6 +228,24 @@ s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, st } +bool +s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri) +{ + + //Send Reply to eNB + //ssize_t n_sent = sctp_send(m_s1mme,reply_msg.msg, reply_msg.N_bytes, enb_sri, 0); + //if(n_sent == -1) + //{ + // m_s1ap_log->console("Failed to send S1 Setup Setup Reply"); + // return false; + //} + + return true; + +} + + + void s1ap::print_enb_ctx_info(const enb_ctx_t &enb_ctx) { From 70f3bcaebad601bd7055d4c8cb65a78b9bf9fca1 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 25 Oct 2017 19:17:36 +0100 Subject: [PATCH 032/172] Starting to parse NAS Attach Request message to get IMSI --- srsepc/hdr/mme/s1ap.h | 5 ++- srsepc/src/mme/s1ap.cc | 80 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 4280cf622..0355e0cda 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -27,6 +27,7 @@ #define S1AP_H #include "srslte/asn1/liblte_s1ap.h" +#include "srslte/asn1/liblte_mme.h" #include "srslte/common/common.h" #include "srslte/common/log.h" @@ -64,7 +65,9 @@ public: bool send_s1_setup_failure(struct sctp_sndrcvinfo *enb_sri); bool send_s1_setup_response(struct sctp_sndrcvinfo *enb_sri); - + + bool handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri); + void print_enb_ctx_info(const enb_ctx_t &enb_ctx); private: diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 7b2074031..717c374c0 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -231,7 +231,85 @@ s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, st bool s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri) { - + m_s1ap_log->console("Received Initial UE Message\n"); + m_s1ap_log->info("Received Initial UE Message\n"); + + //msg->eNB_UE_S1AP_ID; + + LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT attach_req; + + if(!liblte_mme_pack_attach_request_msg(&attach_req, (LIBLTE_BYTE_MSG_STRUCT *) &msg->NAS_PDU.buffer)) + { + m_s1ap_log->console("Error unpacking NAS attach request."); + } + else{ + m_s1ap_log->console("Unpacked NAS attach request."); + } + /*Log unhandled IEs*/ + if(msg->S_TMSI_present){ + m_s1ap_log->warning("S-TMSI present, but not handled."); + } + if(msg->CSG_Id_present){ + m_s1ap_log->warning("S-TMSI present, but not handled."); + } + if(msg->GUMMEI_ID_present){ + m_s1ap_log->warning("GUMMEI ID present, but not handled."); + } + if(msg->CellAccessMode_present){ + m_s1ap_log->warning("Cell Access Mode present, but not handled."); + } + if(msg->GW_TransportLayerAddress_present){ + m_s1ap_log->warning("GW Transport Layer present, but not handled."); + } + if(msg->GW_TransportLayerAddress_present){ + m_s1ap_log->warning("GW Transport Layer present, but not handled."); + } + if(msg->RelayNode_Indicator_present){ + m_s1ap_log->warning("Relay Node Indicator present, but not handled."); + } + if(msg->GUMMEIType_present){ + m_s1ap_log->warning("GUMMEI Type present, but not handled."); + } + if(msg->Tunnel_Information_for_BBF_present){ + m_s1ap_log->warning("Tunnel Information for BBF present, but not handled."); + } + if(msg->SIPTO_L_GW_TransportLayerAddress_present){ + m_s1ap_log->warning("SIPTO GW Transport Layer Address present, but not handled."); + } + if(msg->LHN_ID_present){ + m_s1ap_log->warning("LHN Id present, but not handled."); + } + + /* + typedef struct{ + bool ext; + LIBLTE_S1AP_ENB_UE_S1AP_ID_STRUCT eNB_UE_S1AP_ID; + LIBLTE_S1AP_NAS_PDU_STRUCT NAS_PDU; + LIBLTE_S1AP_TAI_STRUCT TAI; + LIBLTE_S1AP_EUTRAN_CGI_STRUCT EUTRAN_CGI; + LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM_EXT RRC_Establishment_Cause; + LIBLTE_S1AP_S_TMSI_STRUCT S_TMSI; + bool S_TMSI_present; + LIBLTE_S1AP_CSG_ID_STRUCT CSG_Id; + bool CSG_Id_present; + LIBLTE_S1AP_GUMMEI_STRUCT GUMMEI_ID; + bool GUMMEI_ID_present; + LIBLTE_S1AP_CELLACCESSMODE_ENUM_EXT CellAccessMode; + bool CellAccessMode_present; + LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT GW_TransportLayerAddress; + bool GW_TransportLayerAddress_present; + LIBLTE_S1AP_RELAYNODE_INDICATOR_ENUM_EXT RelayNode_Indicator; + bool RelayNode_Indicator_present; + LIBLTE_S1AP_GUMMEITYPE_ENUM_EXT GUMMEIType; + bool GUMMEIType_present; + LIBLTE_S1AP_TUNNELINFORMATION_STRUCT Tunnel_Information_for_BBF; + bool Tunnel_Information_for_BBF_present; + LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT SIPTO_L_GW_TransportLayerAddress; + bool SIPTO_L_GW_TransportLayerAddress_present; + LIBLTE_S1AP_LHN_ID_STRUCT LHN_ID; + bool LHN_ID_present; + }LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT; + */ //Send Reply to eNB //ssize_t n_sent = sctp_send(m_s1mme,reply_msg.msg, reply_msg.N_bytes, enb_sri, 0); //if(n_sent == -1) From e7d6ea530f450c48e62257c3328ded3f75d8ac9d Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 26 Oct 2017 10:32:48 +0100 Subject: [PATCH 033/172] Starting to add HSS class --- srsepc/src/hss/hss.cc | 98 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 srsepc/src/hss/hss.cc diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc new file mode 100644 index 000000000..39063e5a9 --- /dev/null +++ b/srsepc/src/hss/hss.cc @@ -0,0 +1,98 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include //TODO Remove +#include +#include +#include +#include +#include +#include "mme/mme.h" + +namespace srsepc{ + +hss* hss::m_instance = NULL; +boost::mutex hss_instance_mutex; + +hss::hss(): + m_running(false) +{ + m_pool = srslte::byte_buffer_pool::get_instance(); + return; +} + +hss::~hss() +{ + return; +} + +hss* +hss::get_instance(void) +{ + boost::mutex::scoped_lock lock(hss_instance_mutex); + if(NULL == m_instance) { + m_instance = new hss(); + } + return(m_instance); +} + +void +hss::cleanup(void) +{ + boost::mutex::scoped_lock lock(hss_instance_mutex); + if(NULL != m_instance) { + delete m_instance; + m_instance = NULL; + } +} + +int +hss::init(all_args_t* args) +{ + /*Init loggers*/ + if (!args->log_args.filename.compare("stdout")) { + m_logger = &m_logger_stdout; + } else { + m_logger_file.init(args->log_args.filename); + m_logger_file.log("\n--- Software Radio Systems HSS log ---\n\n"); + m_logger = &m_logger_file; + } + + m_hss_log.init("HSS", m_logger); + m_hss_log.set_level(srslte::LOG_LEVEL_DEBUG); + m_hss_log.set_hex_limit(32); + if(m_hss.init(args->s1ap_args, &m_s1ap_log)){ + m_hss_log.error("Error initializing MME S1APP\n"); + exit(-1); + } + m_hss_log.info("Initialized HSS\n"); + m_hss_log.console("Initialized HSS\n"); + return 0; +} + + + +} //namespace srsepc From ef73254707b6023190d8efcae5c54cebdf238896 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 26 Oct 2017 14:20:29 +0100 Subject: [PATCH 034/172] Added new HSS class to compute the authentication vectors. --- srsepc/hdr/hss/hss.h | 76 +++++++++++++++++++++++++++++++++++ srsepc/hdr/mme/mme.h | 14 ++++--- srsepc/src/CMakeLists.txt | 2 + srsepc/src/hss/CMakeLists.txt | 24 +++++++++++ srsepc/src/hss/hss.cc | 26 +++--------- srsepc/src/main.cc | 52 +++++++++++++++++++----- srsepc/src/mme/mme.cc | 5 ++- 7 files changed, 161 insertions(+), 38 deletions(-) create mode 100644 srsepc/hdr/hss/hss.h create mode 100644 srsepc/src/hss/CMakeLists.txt diff --git a/srsepc/hdr/hss/hss.h b/srsepc/hdr/hss/hss.h new file mode 100644 index 000000000..e43613e98 --- /dev/null +++ b/srsepc/hdr/hss/hss.h @@ -0,0 +1,76 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +/****************************************************************************** + * File: hss.h + * Description: Top-level HSS class. Creates and links all + * interfaces and helpers. + *****************************************************************************/ + +#ifndef HSS_H +#define HSS_H + +#include +#include "srslte/common/log.h" +#include "srslte/common/logger_file.h" +#include "srslte/common/log_filter.h" +#include "srslte/common/buffer_pool.h" + + +namespace srsepc{ + +typedef struct{ + std::string ue_file; +}hss_args_t; + + +class hss +{ +public: + static hss* get_instance(void); + static void cleanup(void); + int init(hss_args_t *hss_args, srslte::logger* logger); + +private: + + hss(); + virtual ~hss(); + static hss *m_instance; + + srslte::byte_buffer_pool *m_pool; + + /*Logs*/ + srslte::logger_stdout m_logger_stdout; + srslte::logger_file m_logger_file; + srslte::logger *m_logger; + + srslte::log_filter m_hss_log; + +}; + +} // namespace srsepc + +#endif // MME_H diff --git a/srsepc/hdr/mme/mme.h b/srsepc/hdr/mme/mme.h index b2c67df3d..74c74afed 100644 --- a/srsepc/hdr/mme/mme.h +++ b/srsepc/hdr/mme/mme.h @@ -44,18 +44,20 @@ namespace srsepc{ - +/* typedef struct { std::string s1ap_level; std::string all_level; int s1ap_hex_limit; std::string filename; }log_args_t; +*/ typedef struct{ s1ap_args_t s1ap_args; - log_args_t log_args; -} all_args_t; + //diameter_args_t diameter_args; + //gtpc_args_t gtpc_args; +} mme_args_t; class mme: @@ -64,7 +66,7 @@ class mme: public: static mme* get_instance(void); static void cleanup(void); - int init(all_args_t* args); + int init(mme_args_t* args, srslte::logger *logger); void stop(); int get_s1_mme(); void run_thread(); @@ -80,8 +82,8 @@ private: srslte::byte_buffer_pool *m_pool; /*Logs*/ - srslte::logger_stdout m_logger_stdout; - srslte::logger_file m_logger_file; + //srslte::logger_stdout m_logger_stdout; + //srslte::logger_file m_logger_file; srslte::logger *m_logger; srslte::log_filter m_s1ap_log; diff --git a/srsepc/src/CMakeLists.txt b/srsepc/src/CMakeLists.txt index 1acfcb6b5..d92c5201e 100644 --- a/srsepc/src/CMakeLists.txt +++ b/srsepc/src/CMakeLists.txt @@ -1,5 +1,6 @@ add_subdirectory(mme) +add_subdirectory(hss) # Link libstdc++ and libgcc if(BUILD_STATIC) @@ -14,6 +15,7 @@ endif (RPATH) add_executable(srsepc main.cc ) target_link_libraries(srsepc srsepc_mme + srsepc_hss srslte_upper srslte_common ${CMAKE_THREAD_LIBS_INIT} diff --git a/srsepc/src/hss/CMakeLists.txt b/srsepc/src/hss/CMakeLists.txt new file mode 100644 index 000000000..276612c64 --- /dev/null +++ b/srsepc/src/hss/CMakeLists.txt @@ -0,0 +1,24 @@ +# +# Copyright 2013-2017 Software Radio Systems Limited +# +# This file is part of srsLTE +# +# srsLTE is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# srsLTE is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# A copy of the GNU Affero General Public License can be found in +# the LICENSE file in the top-level directory of this distribution +# and at http://www.gnu.org/licenses/. +# + +file(GLOB SOURCES "*.cc") +add_library(srsepc_hss STATIC ${SOURCES}) +install(TARGETS srsepc_hss DESTINATION ${LIBRARY_DIR}) + diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index 39063e5a9..90b83b595 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -24,21 +24,15 @@ * */ -#include //TODO Remove -#include -#include -#include -#include #include -#include "mme/mme.h" +#include "hss/hss.h" namespace srsepc{ hss* hss::m_instance = NULL; boost::mutex hss_instance_mutex; -hss::hss(): - m_running(false) +hss::hss() { m_pool = srslte::byte_buffer_pool::get_instance(); return; @@ -70,24 +64,14 @@ hss::cleanup(void) } int -hss::init(all_args_t* args) +hss::init(hss_args_t *hss_args, srslte::logger *logger) { /*Init loggers*/ - if (!args->log_args.filename.compare("stdout")) { - m_logger = &m_logger_stdout; - } else { - m_logger_file.init(args->log_args.filename); - m_logger_file.log("\n--- Software Radio Systems HSS log ---\n\n"); - m_logger = &m_logger_file; - } - + m_logger=logger; m_hss_log.init("HSS", m_logger); m_hss_log.set_level(srslte::LOG_LEVEL_DEBUG); m_hss_log.set_hex_limit(32); - if(m_hss.init(args->s1ap_args, &m_s1ap_log)){ - m_hss_log.error("Error initializing MME S1APP\n"); - exit(-1); - } + m_hss_log.info("Initialized HSS\n"); m_hss_log.console("Initialized HSS\n"); return 0; diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index 078a2c7c7..496814244 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -27,6 +27,7 @@ #include #include "srslte/common/bcd_helpers.h" #include "mme/mme.h" +#include "hss/hss.h" using namespace std; using namespace srsepc; @@ -39,6 +40,19 @@ sig_int_handler(int signo){ running = false; } +typedef struct { + std::string all_level; + int hex_limit; + std::string filename; +}log_args_t; + + +typedef struct{ + mme_args_t mme_args; + hss_args_t hss_args; + log_args_t log_args; +}all_args_t; + /********************************************************************** * Program arguments processing ***********************************************************************/ @@ -103,29 +117,29 @@ parse_args(all_args_t *args, int argc, char* argv[]) { { std::stringstream sstr; sstr << std::hex << vm["mme.mme_group"].as(); - sstr >> args->s1ap_args.mme_group; + sstr >> args->mme_args.s1ap_args.mme_group; } { std::stringstream sstr; sstr << std::hex << vm["mme.mme_code"].as(); uint16_t tmp; // Need intermediate uint16_t as uint8_t is treated as char sstr >> tmp; - args->s1ap_args.mme_code = tmp; + args->mme_args.s1ap_args.mme_code = tmp; } { std::stringstream sstr; sstr << std::hex << vm["mme.tac"].as(); - sstr >> args->s1ap_args.tac; + sstr >> args->mme_args.s1ap_args.tac; } // Convert MCC/MNC strings - if(!srslte::string_to_mcc(mcc, &args->s1ap_args.mcc)) { + if(!srslte::string_to_mcc(mcc, &args->mme_args.s1ap_args.mcc)) { cout << "Error parsing enb.mcc:" << mcc << " - must be a 3-digit string." << endl; } - if(!srslte::string_to_mnc(mnc, &args->s1ap_args.mnc)) { + if(!srslte::string_to_mnc(mnc, &args->mme_args.s1ap_args.mnc)) { cout << "Error parsing enb.mnc:" << mnc << " - must be a 2 or 3-digit string." << endl; } - args->s1ap_args.mme_bind_addr = mme_bind_addr; + args->mme_args.s1ap_args.mme_bind_addr = mme_bind_addr; return; } @@ -138,14 +152,34 @@ main (int argc,char * argv[] ) all_args_t args; parse_args(&args, argc, argv); - - args.log_args.filename = std::string("/tmp/epc.log"); + + srslte::logger_stdout logger_stdout; + srslte::logger_file logger_file; + srslte::logger *logger; + + + /*Init logger*/ + args.log_args.filename = std::string("/tmp/epc.log"); //FIXME + if (!args.log_args.filename.compare("stdout")) { + logger = &logger_stdout; + } else { + logger_file.init(args.log_args.filename); + logger_file.log("\n--- Software Radio Systems EPC log ---\n\n"); + logger = &logger_file; + } mme *mme = mme::get_instance(); - if (mme->init(&args)) { + if (mme->init(&args.mme_args, logger)) { cout << "Error initializing MME" << endl; exit(1); } + hss *hss = hss::get_instance(); + if (hss->init(&args.hss_args,logger)) { + cout << "Error initializing HSS" << endl; + exit(1); + } + + mme->start(); while(running) { diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index 0648c6d4e..9cc19030d 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -70,9 +70,10 @@ mme::cleanup(void) } int -mme::init(all_args_t* args) +mme::init(mme_args_t* args, srslte::logger *logger) { /*Init loggers*/ + /* if (!args->log_args.filename.compare("stdout")) { m_logger = &m_logger_stdout; } else { @@ -80,7 +81,7 @@ mme::init(all_args_t* args) m_logger_file.log("\n--- Software Radio Systems MME log ---\n\n"); m_logger = &m_logger_file; } - + */ m_s1ap_log.init("S1AP", m_logger); m_s1ap_log.set_level(srslte::LOG_LEVEL_DEBUG); m_s1ap_log.set_hex_limit(32); From efe258fb6f12c82ebae1c46938d977598d70a919 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 26 Oct 2017 18:26:47 +0100 Subject: [PATCH 035/172] Starting to get the IMSI from the attach request. --- srsepc/hdr/hss/hss.h | 5 +++ srsepc/src/main.cc | 1 - srsepc/src/mme/s1ap.cc | 88 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 88 insertions(+), 6 deletions(-) diff --git a/srsepc/hdr/hss/hss.h b/srsepc/hdr/hss/hss.h index e43613e98..76cd416a5 100644 --- a/srsepc/hdr/hss/hss.h +++ b/srsepc/hdr/hss/hss.h @@ -47,6 +47,7 @@ typedef struct{ }hss_args_t; + class hss { public: @@ -54,6 +55,10 @@ public: static void cleanup(void); int init(hss_args_t *hss_args, srslte::logger* logger); + //bool gen_auth_info_answer(uint64_t imsi); + + //bool get_k_amf_op(uint64_t imsi, *k, *amf, *op); + private: hss(); diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index 496814244..d75bc14d2 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -179,7 +179,6 @@ main (int argc,char * argv[] ) exit(1); } - mme->start(); while(running) { diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 717c374c0..76ee880f2 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -234,17 +234,58 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg m_s1ap_log->console("Received Initial UE Message\n"); m_s1ap_log->info("Received Initial UE Message\n"); - //msg->eNB_UE_S1AP_ID; - LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT attach_req; + LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT pdn_con_req; - if(!liblte_mme_pack_attach_request_msg(&attach_req, (LIBLTE_BYTE_MSG_STRUCT *) &msg->NAS_PDU.buffer)) - { + /*Get */ + + /*Get NAS Attach Request Message*/ + if(!liblte_mme_unpack_attach_request_msg((LIBLTE_BYTE_MSG_STRUCT *) msg->NAS_PDU.buffer, &attach_req)){ m_s1ap_log->console("Error unpacking NAS attach request."); } else{ m_s1ap_log->console("Unpacked NAS attach request."); } + + if(attach_req.eps_mobile_id.type_of_id!=LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI){ + m_s1ap_log->warning("NAS Attach Request: Unhandle UE Id Type"); + } + else{ + m_s1ap_log->console("IMSI: %d", attach_req.eps_mobile_id.imsi); + } + + if(attach_req.old_p_tmsi_signature_present){} + if(attach_req.additional_guti_present){} + if(attach_req.last_visited_registered_tai_present){} + if(attach_req.drx_param_present){} + if(attach_req.ms_network_cap_present){} + if(attach_req.old_lai_present){} + if(attach_req.tmsi_status_present){} + if(attach_req.ms_cm2_present){} + if(attach_req.ms_cm3_present){} + if(attach_req.supported_codecs_present){} + if(attach_req.additional_update_type_present){} + if(attach_req.voice_domain_pref_and_ue_usage_setting_present){} + if(attach_req.device_properties_present){} + if(attach_req.old_guti_type_present){} + + + /*Handle PDN Connctivity Request*/ + liblte_mme_unpack_pdn_connectivity_request_msg(&attach_req.esm_msg, &pdn_con_req); + + pdn_con_req.eps_bearer_id + pdn_con_req.proc_transaction_id = 0x01; // First transaction ID + pdn_con_req.pdn_type = LIBLTE_MME_PDN_TYPE_IPV4; + pdn_con_req.request_type = LIBLTE_MME_REQUEST_TYPE_INITIAL_REQUEST; + + // Set the optional flags + if(pdn_con_req.esm_info_transfer_flag_present){} + if(pdn_con_req.apn_present){} + if(pdn_con_req.protocol_cnfg_opts_present){} + if(pdn_con_req.device_properties_present){} + + + /*Log unhandled IEs*/ if(msg->S_TMSI_present){ m_s1ap_log->warning("S-TMSI present, but not handled."); @@ -279,7 +320,44 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg if(msg->LHN_ID_present){ m_s1ap_log->warning("LHN Id present, but not handled."); } - + + /* + typedef struct{ + LIBLTE_MME_NAS_KEY_SET_ID_STRUCT nas_ksi; + LIBLTE_MME_EPS_MOBILE_ID_STRUCT eps_mobile_id; + LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT ue_network_cap; + LIBLTE_BYTE_MSG_STRUCT esm_msg; + LIBLTE_MME_EPS_MOBILE_ID_STRUCT additional_guti; + LIBLTE_MME_TRACKING_AREA_ID_STRUCT last_visited_registered_tai; + LIBLTE_MME_DRX_PARAMETER_STRUCT drx_param; + LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT ms_network_cap; + LIBLTE_MME_LOCATION_AREA_ID_STRUCT old_lai; + LIBLTE_MME_MOBILE_STATION_CLASSMARK_2_STRUCT ms_cm2; + LIBLTE_MME_MOBILE_STATION_CLASSMARK_3_STRUCT ms_cm3; + LIBLTE_MME_SUPPORTED_CODEC_LIST_STRUCT supported_codecs; + LIBLTE_MME_VOICE_DOMAIN_PREF_AND_UE_USAGE_SETTING_STRUCT voice_domain_pref_and_ue_usage_setting; + LIBLTE_MME_TMSI_STATUS_ENUM tmsi_status; + LIBLTE_MME_ADDITIONAL_UPDATE_TYPE_ENUM additional_update_type; + LIBLTE_MME_DEVICE_PROPERTIES_ENUM device_properties; + LIBLTE_MME_GUTI_TYPE_ENUM old_guti_type; + uint32 old_p_tmsi_signature; + uint8 eps_attach_type; + bool old_p_tmsi_signature_present; + bool additional_guti_present; + bool last_visited_registered_tai_present; + bool drx_param_present; + bool ms_network_cap_present; + bool old_lai_present; + bool tmsi_status_present; + bool ms_cm2_present; + bool ms_cm3_present; + bool supported_codecs_present; + bool additional_update_type_present; + bool voice_domain_pref_and_ue_usage_setting_present; + bool device_properties_present; + bool old_guti_type_present; + }LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT; + */ /* typedef struct{ bool ext; From 8c28335098cf15a9cda1d9333941beb94a49554d Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 26 Oct 2017 19:03:37 +0100 Subject: [PATCH 036/172] Parsing IMSI should be ok. --- srsepc/src/mme/s1ap.cc | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 76ee880f2..6b172fbff 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -251,7 +251,13 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg m_s1ap_log->warning("NAS Attach Request: Unhandle UE Id Type"); } else{ - m_s1ap_log->console("IMSI: %d", attach_req.eps_mobile_id.imsi); + uint64_t temp = 0; + for(int i=14;i>=0;i--) + { + temp *=10; + temp += attach_req.eps_mobile_id.imsi[i]; + } + m_s1ap_log->console("IMSI: %d", temp); } if(attach_req.old_p_tmsi_signature_present){} @@ -273,10 +279,10 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg /*Handle PDN Connctivity Request*/ liblte_mme_unpack_pdn_connectivity_request_msg(&attach_req.esm_msg, &pdn_con_req); - pdn_con_req.eps_bearer_id - pdn_con_req.proc_transaction_id = 0x01; // First transaction ID - pdn_con_req.pdn_type = LIBLTE_MME_PDN_TYPE_IPV4; - pdn_con_req.request_type = LIBLTE_MME_REQUEST_TYPE_INITIAL_REQUEST; + //pdn_con_req.eps_bearer_id + //pdn_con_req.proc_transaction_id = 0x01; // First transaction ID + //pdn_con_req.pdn_type = LIBLTE_MME_PDN_TYPE_IPV4; + //pdn_con_req.request_type = LIBLTE_MME_REQUEST_TYPE_INITIAL_REQUEST; // Set the optional flags if(pdn_con_req.esm_info_transfer_flag_present){} From ae18da83b239003961532d94bda48314e456eda7 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 27 Oct 2017 14:22:04 +0100 Subject: [PATCH 037/172] Starting to add functions to the HSS to get K, AMF and OP. --- srsepc/hdr/hss/hss.h | 6 ++-- srsepc/hdr/mme/s1ap.h | 2 ++ srsepc/hdr/mme/s1ap_nas_transport.h | 46 ++++++++++++++++++++++++++ srsepc/src/hss/hss.cc | 17 ++++++++++ srsepc/src/mme/s1ap.cc | 26 +++++++++++---- srsepc/src/mme/s1ap_nas_transport.cc | 48 ++++++++++++++++++++++++++++ 6 files changed, 134 insertions(+), 11 deletions(-) create mode 100644 srsepc/hdr/mme/s1ap_nas_transport.h create mode 100644 srsepc/src/mme/s1ap_nas_transport.cc diff --git a/srsepc/hdr/hss/hss.h b/srsepc/hdr/hss/hss.h index 76cd416a5..9c8145974 100644 --- a/srsepc/hdr/hss/hss.h +++ b/srsepc/hdr/hss/hss.h @@ -54,10 +54,8 @@ public: static hss* get_instance(void); static void cleanup(void); int init(hss_args_t *hss_args, srslte::logger* logger); - - //bool gen_auth_info_answer(uint64_t imsi); - - //bool get_k_amf_op(uint64_t imsi, *k, *amf, *op); + + bool get_k_amf_op(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op); private: diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 0355e0cda..9e81770c4 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -40,6 +40,7 @@ #include #include "mme/s1ap_common.h" #include "mme/s1ap_mngmt_proc.h" +#include "hss/hss.h" namespace srsepc{ @@ -76,6 +77,7 @@ private: uint32_t m_plmn; srslte::log *m_s1ap_log; + hss *m_hss; int m_s1mme; std::map m_active_enbs; diff --git a/srsepc/hdr/mme/s1ap_nas_transport.h b/srsepc/hdr/mme/s1ap_nas_transport.h new file mode 100644 index 000000000..0c3f71bf8 --- /dev/null +++ b/srsepc/hdr/mme/s1ap_nas_transport.h @@ -0,0 +1,46 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ +#ifndef S1AP_MNGMT_PROC_H +#define S1AP_MNGMT_PROC_H + +#include "srslte/asn1/liblte_s1ap.h" +#include "srslte/common/common.h" +#include "mme/s1ap_common.h" + +namespace srsepc{ + +class s1ap_nas_transport +{ +public: + s1ap_mngmt_proc(srslte::logger s1ap_logger); + virtual ~s1ap_nas_transport(); + + bool unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, uint64_t *imsi); +}; + +} //namespace srsepc + +#endif //S1AP_MNGMT_PROC diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index 90b83b595..0cc05d726 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -77,6 +77,23 @@ hss::init(hss_args_t *hss_args, srslte::logger *logger) return 0; } +bool +hss::get_k_amf_op(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op ) +{ + if(imsi != 1010123456789) + { + return false; + } + else + { + + } + //uint8_t k[16]; + //uint8_t amf[2]; // 3GPP 33.102 v10.0.0 Annex H + //uint8_t op[16]; + + return false; +} } //namespace srsepc diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 6b172fbff..47c9fcfdd 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -49,7 +49,9 @@ s1ap::init(s1ap_args_t s1ap_args, srslte::log *s1ap_log) m_s1ap_log = s1ap_log; m_s1mme = enb_listen(); - + + m_hss = hss::get_instance(); + return 0; } @@ -234,11 +236,14 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg m_s1ap_log->console("Received Initial UE Message\n"); m_s1ap_log->info("Received Initial UE Message\n"); + uint8_t amf[2]; // 3GPP 33.102 v10.0.0 Annex H + uint8_t op[16]; + uint8_t k[16]; + uint64_t imsi; + LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT attach_req; LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT pdn_con_req; - /*Get */ - /*Get NAS Attach Request Message*/ if(!liblte_mme_unpack_attach_request_msg((LIBLTE_BYTE_MSG_STRUCT *) msg->NAS_PDU.buffer, &attach_req)){ m_s1ap_log->console("Error unpacking NAS attach request."); @@ -251,13 +256,13 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg m_s1ap_log->warning("NAS Attach Request: Unhandle UE Id Type"); } else{ - uint64_t temp = 0; + imsi = 0; for(int i=14;i>=0;i--) { - temp *=10; - temp += attach_req.eps_mobile_id.imsi[i]; + imsi *=10; + imsi += attach_req.eps_mobile_id.imsi[i]; } - m_s1ap_log->console("IMSI: %d", temp); + m_s1ap_log->console("IMSI: %d", imsi); } if(attach_req.old_p_tmsi_signature_present){} @@ -326,6 +331,13 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg if(msg->LHN_ID_present){ m_s1ap_log->warning("LHN Id present, but not handled."); } + + if(!m_hss->get_k_amf_op(imsi, k, amf, op)) + { + m_s1ap_log->info("User %d not found",imsi); + } + + /* typedef struct{ diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc new file mode 100644 index 000000000..701e8200f --- /dev/null +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -0,0 +1,48 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "mme/s1ap.h" +#include "mme/s1ap_nas_transport.h" + +namespace srsepc{ + +s1ap_nas_transport::s1ap_nas_transport(srslte::logger *s1ap_logger) +{ + m_s1ap_logger=s1ap_logger; +} + +s1ap_nas_transport::~s1ap_nas_transport() +{ +} + +bool +s1ap_nas_transport::initial_ue_message(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, uint64_t *imsi) +{ + return true; +} + + +} //namespace srsepc From 81827f891bffcffac6ff31d565bcbba1a4b35e75 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 31 Oct 2017 13:53:24 +0000 Subject: [PATCH 038/172] Decoding correctly the NAS Attach request message now. --- srsepc/hdr/mme/s1ap.h | 7 ++++--- srsepc/src/mme/s1ap.cc | 24 ++++++++++++++++++++---- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 9e81770c4..dfadd12e8 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -73,9 +73,10 @@ public: private: - s1ap_args_t m_s1ap_args; - uint32_t m_plmn; - srslte::log *m_s1ap_log; + s1ap_args_t m_s1ap_args; + uint32_t m_plmn; + srslte::byte_buffer_pool *m_pool; + srslte::log *m_s1ap_log; hss *m_hss; int m_s1mme; diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 47c9fcfdd..f9ccaceeb 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -51,6 +51,8 @@ s1ap::init(s1ap_args_t s1ap_args, srslte::log *s1ap_log) m_s1mme = enb_listen(); m_hss = hss::get_instance(); + + m_pool = srslte::byte_buffer_pool::get_instance(); return 0; } @@ -245,13 +247,27 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT pdn_con_req; /*Get NAS Attach Request Message*/ - if(!liblte_mme_unpack_attach_request_msg((LIBLTE_BYTE_MSG_STRUCT *) msg->NAS_PDU.buffer, &attach_req)){ - m_s1ap_log->console("Error unpacking NAS attach request."); + uint8_t pd, msg_type; + + srslte::byte_buffer_t *nas_msg = m_pool->allocate(); + memcpy(nas_msg->msg, &msg->NAS_PDU.buffer, msg->NAS_PDU.n_octets); + nas_msg->N_bytes = msg->NAS_PDU.n_octets; + liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &pd, &msg_type); + + if(msg_type!=LIBLTE_MME_MSG_TYPE_ATTACH_REQUEST){ + m_s1ap_log->error("Unhandled NAS message within the Initial UE message\n"); + return false; } - else{ - m_s1ap_log->console("Unpacked NAS attach request."); + + LIBLTE_ERROR_ENUM err = liblte_mme_unpack_attach_request_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &attach_req); + if(err != LIBLTE_SUCCESS){ + m_s1ap_log->console("Error unpacking NAS attach request. Error: %s\n", liblte_error_text[err]); + return false; } + m_s1ap_log->console("Unpacked NAS attach request.\n"); + + if(attach_req.eps_mobile_id.type_of_id!=LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI){ m_s1ap_log->warning("NAS Attach Request: Unhandle UE Id Type"); } From 3fd552c0e2462514b68b57f0051eecb56d9e60b5 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 31 Oct 2017 15:58:33 +0000 Subject: [PATCH 039/172] Fixed bug in printing IMSI. IMSI decoded correctly from NAS attach request. --- srsepc/src/mme/s1ap.cc | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index f9ccaceeb..9483da9e4 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -24,6 +24,8 @@ * */ +#include +#include #include "srslte/common/bcd_helpers.h" #include "mme/s1ap.h" @@ -265,21 +267,19 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg return false; } - m_s1ap_log->console("Unpacked NAS attach request.\n"); - - + m_s1ap_log->info("Received Attach Request\n"); if(attach_req.eps_mobile_id.type_of_id!=LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI){ m_s1ap_log->warning("NAS Attach Request: Unhandle UE Id Type"); + return false; } - else{ - imsi = 0; - for(int i=14;i>=0;i--) - { - imsi *=10; - imsi += attach_req.eps_mobile_id.imsi[i]; - } - m_s1ap_log->console("IMSI: %d", imsi); + + imsi = 0; + for(int i=0;i<=14;i++) + { + imsi += attach_req.eps_mobile_id.imsi[i]*std::pow(10,14-i); + //std::cout << (uint16_t) attach_req.eps_mobile_id.imsi[i] << " "; } + m_s1ap_log->console("IMSI: %015lu\n", imsi); if(attach_req.old_p_tmsi_signature_present){} if(attach_req.additional_guti_present){} From 6c60c493e72416ff85e1de1d2d4a46fd4ff8c89e Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 31 Oct 2017 18:05:26 +0000 Subject: [PATCH 040/172] Hard-coded k, amf and op (for now). --- srsepc/src/hss/hss.cc | 17 ++++++++++---- srsepc/src/mme/s1ap.cc | 53 +++++++++++++++++++++++++++++++----------- 2 files changed, 53 insertions(+), 17 deletions(-) diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index 0cc05d726..e64a3accb 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -81,19 +81,28 @@ bool hss::get_k_amf_op(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op ) { + uint8_t k_tmp[16]; + for(int i=0;i<8;i++) + { + k_tmp[2*i]=i; + k_tmp[2*i+1]=i; + } + uint8_t amf_tmp[2]={0x80,0x00}; + uint8_t op_tmp[16]={0x63,0xbf,0xA5,0x0E,0xE6,0x52,0x33,0x65,0xFF,0x14,0xC1,0xF4,0x5F,0x88,0x73,0x7D}; if(imsi != 1010123456789) { return false; } - else - { + m_hss_log.console("Found User %015lu\n",imsi); + memcpy(k,k_tmp,16); + memcpy(amf,amf_tmp,2); + memcpy(op,op_tmp,16); - } //uint8_t k[16]; //uint8_t amf[2]; // 3GPP 33.102 v10.0.0 Annex H //uint8_t op[16]; - return false; + return true; } } //namespace srsepc diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 9483da9e4..c65c55d58 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -263,13 +263,13 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg LIBLTE_ERROR_ENUM err = liblte_mme_unpack_attach_request_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &attach_req); if(err != LIBLTE_SUCCESS){ - m_s1ap_log->console("Error unpacking NAS attach request. Error: %s\n", liblte_error_text[err]); + m_s1ap_log->error("Error unpacking NAS attach request. Error: %s\n", liblte_error_text[err]); return false; } m_s1ap_log->info("Received Attach Request\n"); if(attach_req.eps_mobile_id.type_of_id!=LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI){ - m_s1ap_log->warning("NAS Attach Request: Unhandle UE Id Type"); + m_s1ap_log->error("NAS Attach Request: Unhandle UE Id Type"); return false; } @@ -277,7 +277,6 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg for(int i=0;i<=14;i++) { imsi += attach_req.eps_mobile_id.imsi[i]*std::pow(10,14-i); - //std::cout << (uint16_t) attach_req.eps_mobile_id.imsi[i] << " "; } m_s1ap_log->console("IMSI: %015lu\n", imsi); @@ -298,21 +297,31 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg /*Handle PDN Connctivity Request*/ - liblte_mme_unpack_pdn_connectivity_request_msg(&attach_req.esm_msg, &pdn_con_req); - - //pdn_con_req.eps_bearer_id - //pdn_con_req.proc_transaction_id = 0x01; // First transaction ID - //pdn_con_req.pdn_type = LIBLTE_MME_PDN_TYPE_IPV4; - //pdn_con_req.request_type = LIBLTE_MME_REQUEST_TYPE_INITIAL_REQUEST; + err = liblte_mme_unpack_pdn_connectivity_request_msg(&attach_req.esm_msg, &pdn_con_req); + if(err != LIBLTE_SUCCESS){ + m_s1ap_log->error("Error unpacking NAS PDN Connectivity Request. Error: %s\n", liblte_error_text[err]); + return false; + } - // Set the optional flags + uint8_t eps_bearer_id = pdn_con_req.eps_bearer_id; //TODO: Unused + uint8_t proc_transaction_id = pdn_con_req.proc_transaction_id; //TODO: Transaction ID unused + if(pdn_con_req.pdn_type != LIBLTE_MME_PDN_TYPE_IPV4) + { + m_s1ap_log->error("PDN Connectivity Request: Only IPv4 connectivity supported.\n"); + return false; + } + if(pdn_con_req.request_type != LIBLTE_MME_REQUEST_TYPE_INITIAL_REQUEST) + { + m_s1ap_log->error("PDN Connectivity Request: Only Initial Request supported.\n"); + return false; + } + + //Handle the optional flags if(pdn_con_req.esm_info_transfer_flag_present){} if(pdn_con_req.apn_present){} if(pdn_con_req.protocol_cnfg_opts_present){} if(pdn_con_req.device_properties_present){} - - /*Log unhandled IEs*/ if(msg->S_TMSI_present){ m_s1ap_log->warning("S-TMSI present, but not handled."); @@ -350,7 +359,9 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg if(!m_hss->get_k_amf_op(imsi, k, amf, op)) { - m_s1ap_log->info("User %d not found",imsi); + m_s1ap_log->console("User not found. IMSI %015lu\n",imsi); + m_s1ap_log->info("User not found. IMSI %015lu\n",imsi); + return false; } @@ -393,6 +404,22 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg }LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT; */ /* + typedef struct{ + LIBLTE_MME_ACCESS_POINT_NAME_STRUCT apn; + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + LIBLTE_MME_ESM_INFO_TRANSFER_FLAG_ENUM esm_info_transfer_flag; + LIBLTE_MME_DEVICE_PROPERTIES_ENUM device_properties; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + uint8 pdn_type; + uint8 request_type; + bool esm_info_transfer_flag_present; + bool apn_present; + bool protocol_cnfg_opts_present; + bool device_properties_present; + }LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT; + */ + /* typedef struct{ bool ext; LIBLTE_S1AP_ENB_UE_S1AP_ID_STRUCT eNB_UE_S1AP_ID; From 1a8a2f738b1e50716f5abacd45e4b7bd38162779 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 31 Oct 2017 19:34:10 +0000 Subject: [PATCH 041/172] Starting to add SQN generation. --- srsepc/hdr/hss/hss.h | 1 + srsepc/src/hss/hss.cc | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/srsepc/hdr/hss/hss.h b/srsepc/hdr/hss/hss.h index 9c8145974..b9251cc9d 100644 --- a/srsepc/hdr/hss/hss.h +++ b/srsepc/hdr/hss/hss.h @@ -55,6 +55,7 @@ public: static void cleanup(void); int init(hss_args_t *hss_args, srslte::logger* logger); + uint64_t get_sqn(); bool get_k_amf_op(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op); private: diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index e64a3accb..7045d848d 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -98,11 +98,13 @@ hss::get_k_amf_op(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op ) memcpy(amf,amf_tmp,2); memcpy(op,op_tmp,16); - //uint8_t k[16]; - //uint8_t amf[2]; // 3GPP 33.102 v10.0.0 Annex H - //uint8_t op[16]; - return true; } +uint64_t +hss::get_sqn( ) +{ + return 0; +} + } //namespace srsepc From 470c8151963656e4b7ac3600f17fbc055cf6553b Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 1 Nov 2017 14:07:44 +0000 Subject: [PATCH 042/172] Generating RAND --- srsepc/hdr/hss/hss.h | 5 +++- srsepc/src/hss/hss.cc | 62 +++++++++++++++++++++++++++++++++++------- srsepc/src/mme/s1ap.cc | 2 +- 3 files changed, 57 insertions(+), 12 deletions(-) diff --git a/srsepc/hdr/hss/hss.h b/srsepc/hdr/hss/hss.h index b9251cc9d..c08545a9f 100644 --- a/srsepc/hdr/hss/hss.h +++ b/srsepc/hdr/hss/hss.h @@ -55,8 +55,10 @@ public: static void cleanup(void); int init(hss_args_t *hss_args, srslte::logger* logger); - uint64_t get_sqn(); + void get_sqn(uint8_t sqn[6]); + void gen_rand(uint8_t rand_[16]); bool get_k_amf_op(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op); + bool gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *kasme, uint8_t *autn, uint8_t *rand, uint8_t *xres); private: @@ -64,6 +66,7 @@ private: virtual ~hss(); static hss *m_instance; + uint64_t m_sqn; //48 bits srslte::byte_buffer_pool *m_pool; /*Logs*/ diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index 7045d848d..9b6159c13 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -23,7 +23,8 @@ * and at http://www.gnu.org/licenses/. * */ - +#include /* srand, rand */ +#include /* time */ #include #include "hss/hss.h" @@ -33,6 +34,7 @@ hss* hss::m_instance = NULL; boost::mutex hss_instance_mutex; hss::hss() + :m_sqn(0) { m_pool = srslte::byte_buffer_pool::get_instance(); return; @@ -72,27 +74,52 @@ hss::init(hss_args_t *hss_args, srslte::logger *logger) m_hss_log.set_level(srslte::LOG_LEVEL_DEBUG); m_hss_log.set_hex_limit(32); + srand(time(NULL)); + m_hss_log.info("Initialized HSS\n"); m_hss_log.console("Initialized HSS\n"); return 0; } +bool +hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *kasme, uint8_t *autn, uint8_t *rand, uint8_t *xres) +{ + uint8_t k[16]; + uint8_t amf[2]; + uint8_t op[16]; + //uint8_t rand[16]; + uint8_t sqn[6]; + + if(!get_k_amf_op(imsi,k,amf,op)) + { + return false; + } + gen_rand(rand); + get_sqn(sqn); + + return true; +} + bool hss::get_k_amf_op(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op ) { uint8_t k_tmp[16]; + uint8_t amf_tmp[2]={0x80,0x00}; + uint8_t op_tmp[16]={0x63,0xbf,0xA5,0x0E,0xE6,0x52,0x33,0x65,0xFF,0x14,0xC1,0xF4,0x5F,0x88,0x73,0x7D}; + + if(imsi != 1010123456789) + { + m_hss_log.console("Usernot found. IMSI: %015lu\n",imsi); + return false; + } + for(int i=0;i<8;i++) { k_tmp[2*i]=i; k_tmp[2*i+1]=i; } - uint8_t amf_tmp[2]={0x80,0x00}; - uint8_t op_tmp[16]={0x63,0xbf,0xA5,0x0E,0xE6,0x52,0x33,0x65,0xFF,0x14,0xC1,0xF4,0x5F,0x88,0x73,0x7D}; - if(imsi != 1010123456789) - { - return false; - } + m_hss_log.console("Found User %015lu\n",imsi); memcpy(k,k_tmp,16); memcpy(amf,amf_tmp,2); @@ -101,10 +128,25 @@ hss::get_k_amf_op(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op ) return true; } -uint64_t -hss::get_sqn( ) +void +hss::get_sqn(uint8_t sqn[6]) { - return 0; + for (int i=0; i<6; i++) + { + sqn[i] = ((uint8_t *)&m_sqn)[i]; + } + m_sqn++; + return; //TODO See TS 33.102, Annex C +} + +void +hss::gen_rand(uint8_t rand_[16]) +{ + for(int i=0;i<16;i++) + { + rand_[i]=rand()%256; //Pulls on byte at a time. It's slow, but does not depend on RAND_MAX. + } + return; } } //namespace srsepc diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index c65c55d58..0204e1ddf 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -363,7 +363,7 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg m_s1ap_log->info("User not found. IMSI %015lu\n",imsi); return false; } - + /* From 9c54a8b7debd6f25b2a7e0aa58bd6c529f1ee595 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 1 Nov 2017 15:14:41 +0000 Subject: [PATCH 043/172] Initial code to generate Kasme, rand, autn and xres --- srsepc/hdr/hss/hss.h | 2 +- srsepc/src/hss/hss.cc | 39 +++++++++++++++- srsepc/src/mme/s1ap.cc | 103 ++++------------------------------------- 3 files changed, 47 insertions(+), 97 deletions(-) diff --git a/srsepc/hdr/hss/hss.h b/srsepc/hdr/hss/hss.h index c08545a9f..df19aed4e 100644 --- a/srsepc/hdr/hss/hss.h +++ b/srsepc/hdr/hss/hss.h @@ -58,7 +58,7 @@ public: void get_sqn(uint8_t sqn[6]); void gen_rand(uint8_t rand_[16]); bool get_k_amf_op(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op); - bool gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *kasme, uint8_t *autn, uint8_t *rand, uint8_t *xres); + bool gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres); private: diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index 9b6159c13..e5dc85b77 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -27,6 +27,9 @@ #include /* time */ #include #include "hss/hss.h" +#include "srslte/common/security.h" + +using namespace srslte; namespace srsepc{ @@ -82,14 +85,21 @@ hss::init(hss_args_t *hss_args, srslte::logger *logger) } bool -hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *kasme, uint8_t *autn, uint8_t *rand, uint8_t *xres) +hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres) { uint8_t k[16]; uint8_t amf[2]; uint8_t op[16]; - //uint8_t rand[16]; uint8_t sqn[6]; + uint8_t ck[16]; + uint8_t ik[16]; + uint8_t ak[6]; + uint8_t mac[8]; + + uint16_t mcc=1; + uint16_t mnc=1; + if(!get_k_amf_op(imsi,k,amf,op)) { return false; @@ -97,6 +107,31 @@ hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *kasme, uint8_t *autn, gen_rand(rand); get_sqn(sqn); + security_milenage_f2345( k, + op, + rand, + xres, + ck, + ik, + ak); + + security_milenage_f1( k, + op, + rand, + sqn, + amf, + mac); + + // Generate K_asme + security_generate_k_asme( ck, + ik, + ak, + sqn, + mcc, + mnc, + k_asme); + + return true; } diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 0204e1ddf..83a5d946f 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -356,107 +356,22 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg if(msg->LHN_ID_present){ m_s1ap_log->warning("LHN Id present, but not handled."); } - - if(!m_hss->get_k_amf_op(imsi, k, amf, op)) + + + uint8_t k_asme[32]; + uint8_t autn[16]; + uint8_t rand[6]; + uint8_t xres[16]; + + if(!m_hss->gen_auth_info_answer_milenage(imsi, k_asme, autn, rand, xres)) { m_s1ap_log->console("User not found. IMSI %015lu\n",imsi); m_s1ap_log->info("User not found. IMSI %015lu\n",imsi); return false; } - + m_s1ap_nas_transport->gen_auth_request(); - /* - typedef struct{ - LIBLTE_MME_NAS_KEY_SET_ID_STRUCT nas_ksi; - LIBLTE_MME_EPS_MOBILE_ID_STRUCT eps_mobile_id; - LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT ue_network_cap; - LIBLTE_BYTE_MSG_STRUCT esm_msg; - LIBLTE_MME_EPS_MOBILE_ID_STRUCT additional_guti; - LIBLTE_MME_TRACKING_AREA_ID_STRUCT last_visited_registered_tai; - LIBLTE_MME_DRX_PARAMETER_STRUCT drx_param; - LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT ms_network_cap; - LIBLTE_MME_LOCATION_AREA_ID_STRUCT old_lai; - LIBLTE_MME_MOBILE_STATION_CLASSMARK_2_STRUCT ms_cm2; - LIBLTE_MME_MOBILE_STATION_CLASSMARK_3_STRUCT ms_cm3; - LIBLTE_MME_SUPPORTED_CODEC_LIST_STRUCT supported_codecs; - LIBLTE_MME_VOICE_DOMAIN_PREF_AND_UE_USAGE_SETTING_STRUCT voice_domain_pref_and_ue_usage_setting; - LIBLTE_MME_TMSI_STATUS_ENUM tmsi_status; - LIBLTE_MME_ADDITIONAL_UPDATE_TYPE_ENUM additional_update_type; - LIBLTE_MME_DEVICE_PROPERTIES_ENUM device_properties; - LIBLTE_MME_GUTI_TYPE_ENUM old_guti_type; - uint32 old_p_tmsi_signature; - uint8 eps_attach_type; - bool old_p_tmsi_signature_present; - bool additional_guti_present; - bool last_visited_registered_tai_present; - bool drx_param_present; - bool ms_network_cap_present; - bool old_lai_present; - bool tmsi_status_present; - bool ms_cm2_present; - bool ms_cm3_present; - bool supported_codecs_present; - bool additional_update_type_present; - bool voice_domain_pref_and_ue_usage_setting_present; - bool device_properties_present; - bool old_guti_type_present; - }LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT; - */ - /* - typedef struct{ - LIBLTE_MME_ACCESS_POINT_NAME_STRUCT apn; - LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; - LIBLTE_MME_ESM_INFO_TRANSFER_FLAG_ENUM esm_info_transfer_flag; - LIBLTE_MME_DEVICE_PROPERTIES_ENUM device_properties; - uint8 eps_bearer_id; - uint8 proc_transaction_id; - uint8 pdn_type; - uint8 request_type; - bool esm_info_transfer_flag_present; - bool apn_present; - bool protocol_cnfg_opts_present; - bool device_properties_present; - }LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT; - */ - /* - typedef struct{ - bool ext; - LIBLTE_S1AP_ENB_UE_S1AP_ID_STRUCT eNB_UE_S1AP_ID; - LIBLTE_S1AP_NAS_PDU_STRUCT NAS_PDU; - LIBLTE_S1AP_TAI_STRUCT TAI; - LIBLTE_S1AP_EUTRAN_CGI_STRUCT EUTRAN_CGI; - LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM_EXT RRC_Establishment_Cause; - LIBLTE_S1AP_S_TMSI_STRUCT S_TMSI; - bool S_TMSI_present; - LIBLTE_S1AP_CSG_ID_STRUCT CSG_Id; - bool CSG_Id_present; - LIBLTE_S1AP_GUMMEI_STRUCT GUMMEI_ID; - bool GUMMEI_ID_present; - LIBLTE_S1AP_CELLACCESSMODE_ENUM_EXT CellAccessMode; - bool CellAccessMode_present; - LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT GW_TransportLayerAddress; - bool GW_TransportLayerAddress_present; - LIBLTE_S1AP_RELAYNODE_INDICATOR_ENUM_EXT RelayNode_Indicator; - bool RelayNode_Indicator_present; - LIBLTE_S1AP_GUMMEITYPE_ENUM_EXT GUMMEIType; - bool GUMMEIType_present; - LIBLTE_S1AP_TUNNELINFORMATION_STRUCT Tunnel_Information_for_BBF; - bool Tunnel_Information_for_BBF_present; - LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT SIPTO_L_GW_TransportLayerAddress; - bool SIPTO_L_GW_TransportLayerAddress_present; - LIBLTE_S1AP_LHN_ID_STRUCT LHN_ID; - bool LHN_ID_present; - }LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT; - */ - //Send Reply to eNB - //ssize_t n_sent = sctp_send(m_s1mme,reply_msg.msg, reply_msg.N_bytes, enb_sri, 0); - //if(n_sent == -1) - //{ - // m_s1ap_log->console("Failed to send S1 Setup Setup Reply"); - // return false; - //} - return true; } From 7737acb970b7bf23117a6b95119edd02c6638d40 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 1 Nov 2017 19:14:16 +0000 Subject: [PATCH 044/172] Starting to fill the Attach Request message. --- srsepc/hdr/mme/s1ap.h | 2 ++ srsepc/hdr/mme/s1ap_nas_transport.h | 14 ++++++--- srsepc/src/mme/s1ap.cc | 11 +++---- srsepc/src/mme/s1ap_nas_transport.cc | 46 +++++++++++++++++++++++++--- 4 files changed, 59 insertions(+), 14 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index dfadd12e8..a3dd63ffe 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -40,6 +40,7 @@ #include #include "mme/s1ap_common.h" #include "mme/s1ap_mngmt_proc.h" +#include "mme/s1ap_nas_transport.h" #include "hss/hss.h" namespace srsepc{ @@ -83,6 +84,7 @@ private: std::map m_active_enbs; s1ap_mngmt_proc m_s1ap_mngmt_proc; + s1ap_nas_transport m_s1ap_nas_transport; }; diff --git a/srsepc/hdr/mme/s1ap_nas_transport.h b/srsepc/hdr/mme/s1ap_nas_transport.h index 0c3f71bf8..878da369e 100644 --- a/srsepc/hdr/mme/s1ap_nas_transport.h +++ b/srsepc/hdr/mme/s1ap_nas_transport.h @@ -23,8 +23,8 @@ * and at http://www.gnu.org/licenses/. * */ -#ifndef S1AP_MNGMT_PROC_H -#define S1AP_MNGMT_PROC_H +#ifndef S1AP_NAS_TRANSPORT_H +#define S1AP_NAS_TRANSPORT_H #include "srslte/asn1/liblte_s1ap.h" #include "srslte/common/common.h" @@ -35,12 +35,18 @@ namespace srsepc{ class s1ap_nas_transport { public: - s1ap_mngmt_proc(srslte::logger s1ap_logger); + s1ap_nas_transport(); virtual ~s1ap_nas_transport(); + void set_log(srslte::log *s1ap_logger); bool unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, uint64_t *imsi); + bool pack_authentication_request(); + +private: + srslte::log *m_s1ap_log; + }; } //namespace srsepc -#endif //S1AP_MNGMT_PROC +#endif //S1AP_NAS_TRANSPORT diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 83a5d946f..ce25a26ec 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -45,17 +45,16 @@ s1ap::init(s1ap_args_t s1ap_args, srslte::log *s1ap_log) { m_s1ap_args = s1ap_args; - srslte::s1ap_mccmnc_to_plmn(s1ap_args.mcc, s1ap_args.mnc, &m_plmn); m_s1ap_log = s1ap_log; + m_s1ap_nas_transport.set_log(s1ap_log); + + m_hss = hss::get_instance(); + m_pool = srslte::byte_buffer_pool::get_instance(); m_s1mme = enb_listen(); - m_hss = hss::get_instance(); - - m_pool = srslte::byte_buffer_pool::get_instance(); - return 0; } @@ -370,7 +369,7 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg return false; } - m_s1ap_nas_transport->gen_auth_request(); + m_s1ap_nas_transport.pack_authentication_request(); return true; diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 701e8200f..18c2ad072 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -29,20 +29,58 @@ namespace srsepc{ -s1ap_nas_transport::s1ap_nas_transport(srslte::logger *s1ap_logger) +s1ap_nas_transport::s1ap_nas_transport() { - m_s1ap_logger=s1ap_logger; + return; } s1ap_nas_transport::~s1ap_nas_transport() { + return; +} + +void +s1ap_nas_transport::set_log(srslte::log *s1ap_log) +{ + m_s1ap_log=s1ap_log; + return; } bool -s1ap_nas_transport::initial_ue_message(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, uint64_t *imsi) +s1ap_nas_transport::unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, uint64_t *imsi) { return true; } - +bool +s1ap_nas_transport::pack_authentication_request(uint8_t *autn,uint8_t *rand) +{ + + LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT pdu; + memcpy(pdu.autn , autn, 16); + memcpy(pdu.rand, rand, 16); + pdu.tsg_flag=LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; + pdu.nas_ksi=0; + + return true; + + //typedef struct{ + // LIBLTE_MME_NAS_KEY_SET_ID_STRUCT nas_ksi; + // uint8 autn[16]; + // uint8 rand[16]; + //}LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT; + + //typedef struct{ + // LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_ENUM tsc_flag; + // uint8 nas_ksi; + //}LIBLTE_MME_NAS_KEY_SET_ID_STRUCT; + + //typedef enum{ + // LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE = 0, + // LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_MAPPED, + // LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_N_ITEMS, + //}LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_ENUM; + +} + } //namespace srsepc From fae584dc91669f2600cd020ac97275786dcf9292 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 2 Nov 2017 15:07:28 +0000 Subject: [PATCH 045/172] Packed authentication request message. Code needs cleanup and testing. --- srsepc/hdr/mme/s1ap.h | 1 + srsepc/hdr/mme/s1ap_nas_transport.h | 2 +- srsepc/src/mme/s1ap.cc | 72 ++++++++++++++++++++++++++-- srsepc/src/mme/s1ap_nas_transport.cc | 24 ++-------- 4 files changed, 73 insertions(+), 26 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index a3dd63ffe..2ab1d74c1 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -82,6 +82,7 @@ private: hss *m_hss; int m_s1mme; std::map m_active_enbs; + uint32_t m_next_mme_ue_s1ap_id; s1ap_mngmt_proc m_s1ap_mngmt_proc; s1ap_nas_transport m_s1ap_nas_transport; diff --git a/srsepc/hdr/mme/s1ap_nas_transport.h b/srsepc/hdr/mme/s1ap_nas_transport.h index 878da369e..db7c8c829 100644 --- a/srsepc/hdr/mme/s1ap_nas_transport.h +++ b/srsepc/hdr/mme/s1ap_nas_transport.h @@ -40,7 +40,7 @@ public: void set_log(srslte::log *s1ap_logger); bool unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, uint64_t *imsi); - bool pack_authentication_request(); + bool pack_authentication_request(uint8_t *autn,uint8_t *rand); private: srslte::log *m_s1ap_log; diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index ce25a26ec..8ec436cd7 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -32,7 +32,8 @@ namespace srsepc{ s1ap::s1ap(): - m_s1mme(-1) + m_s1mme(-1), + m_next_mme_ue_s1ap_id(0) { } @@ -183,6 +184,7 @@ s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, st std::string mnc_str, mcc_str; enb_ctx_t enb_ctx; srslte::byte_buffer_t reply_msg; + LIBLTE_S1AP_S1AP_PDU_STRUCT reply_pdu; if(!m_s1ap_mngmt_proc.unpack_s1_setup_request(msg, &enb_ctx)) @@ -247,6 +249,8 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT attach_req; LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT pdn_con_req; + /*Get info from initial UE message*/ + uint32_t enb_ue_s1ap_id = msg->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; /*Get NAS Attach Request Message*/ uint8_t pd, msg_type; @@ -369,10 +373,70 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg return false; } - m_s1ap_nas_transport.pack_authentication_request(); - - return true; + //Pack NAS Authentication Request in Downlink NAS Transport msg + srslte::byte_buffer_t *nas_buffer; + srslte::byte_buffer_t *reply_msg = m_pool->allocate(); + //Setup initiating message + LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu; + tx_pdu.ext = false; + tx_pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE; + + LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *init = &tx_pdu.choice.initiatingMessage; + init->procedureCode = LIBLTE_S1AP_PROC_ID_DOWNLINKNASTRANSPORT; + init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DOWNLINKNASTRANSPORT; + + //Setup Dw NAS message + LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT *dw_nas = &init->choice.DownlinkNASTransport; + dw_nas->ext=false; + dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = m_next_mme_ue_s1ap_id++; + dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = enb_ue_s1ap_id; + dw_nas->HandoverRestrictionList_present=false; + dw_nas->SubscriberProfileIDforRFP_present=false; + /* + typedef struct{ + bool ext; + LIBLTE_S1AP_MME_UE_S1AP_ID_STRUCT MME_UE_S1AP_ID; + LIBLTE_S1AP_ENB_UE_S1AP_ID_STRUCT eNB_UE_S1AP_ID; + LIBLTE_S1AP_NAS_PDU_STRUCT NAS_PDU; + LIBLTE_S1AP_HANDOVERRESTRICTIONLIST_STRUCT HandoverRestrictionList; + bool HandoverRestrictionList_present; + LIBLTE_S1AP_SUBSCRIBERPROFILEIDFORRFP_STRUCT SubscriberProfileIDforRFP; + bool SubscriberProfileIDforRFP_present; + }LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT; + */ + + LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT auth_req; + memcpy(auth_req.autn , autn, 16); + memcpy(auth_req.rand, rand, 16); + auth_req.nas_ksi.tsc_flag=LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; + auth_req.nas_ksi.nas_ksi=0; + + + // NAS_PDU + nas_buffer = m_pool->allocate(); + err = liblte_mme_pack_authentication_request_msg(&auth_req, (LIBLTE_BYTE_MSG_STRUCT *) reply_msg); + if(err != LIBLTE_SUCCESS) + { + m_s1ap_log->console("Error packing Athentication Request"); + return false; + } + + memcpy(dw_nas->NAS_PDU.buffer, reply_msg->msg, reply_msg->N_bytes); + dw_nas->NAS_PDU.n_octets = reply_msg->N_bytes; + + + //Send Reply to eNB + ssize_t n_sent = sctp_send(m_s1mme,reply_msg->msg, reply_msg->N_bytes, enb_sri, 0); + if(n_sent == -1) + { + m_s1ap_log->console("Failed to send S1 Setup Setup Reply"); + return false; + } + + m_pool->deallocate(reply_msg); + //TODO Start T3460 Timer! + return true; } diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 18c2ad072..bf8a8d0a4 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -59,28 +59,10 @@ s1ap_nas_transport::pack_authentication_request(uint8_t *autn,uint8_t *rand) LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT pdu; memcpy(pdu.autn , autn, 16); memcpy(pdu.rand, rand, 16); - pdu.tsg_flag=LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; - pdu.nas_ksi=0; - + pdu.nas_ksi.tsc_flag=LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; + pdu.nas_ksi.nas_ksi=0; + return true; - - //typedef struct{ - // LIBLTE_MME_NAS_KEY_SET_ID_STRUCT nas_ksi; - // uint8 autn[16]; - // uint8 rand[16]; - //}LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT; - - //typedef struct{ - // LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_ENUM tsc_flag; - // uint8 nas_ksi; - //}LIBLTE_MME_NAS_KEY_SET_ID_STRUCT; - - //typedef enum{ - // LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE = 0, - // LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_MAPPED, - // LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_N_ITEMS, - //}LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_ENUM; - } } //namespace srsepc From 8a81149ca3e410056dbadba7daf38699aa9c62bb Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 2 Nov 2017 15:57:19 +0000 Subject: [PATCH 046/172] eNB Receiving Downlink NAS Transport. --- srsepc/src/mme/s1ap.cc | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 8ec436cd7..243e4c6b0 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -413,27 +413,34 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg auth_req.nas_ksi.nas_ksi=0; - // NAS_PDU + // Pack NAS_PDU nas_buffer = m_pool->allocate(); - err = liblte_mme_pack_authentication_request_msg(&auth_req, (LIBLTE_BYTE_MSG_STRUCT *) reply_msg); + err = liblte_mme_pack_authentication_request_msg(&auth_req, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); if(err != LIBLTE_SUCCESS) { m_s1ap_log->console("Error packing Athentication Request"); return false; } - memcpy(dw_nas->NAS_PDU.buffer, reply_msg->msg, reply_msg->N_bytes); - dw_nas->NAS_PDU.n_octets = reply_msg->N_bytes; + memcpy(dw_nas->NAS_PDU.buffer, nas_buffer->msg, nas_buffer->N_bytes); + dw_nas->NAS_PDU.n_octets = nas_buffer->N_bytes; + //Pack Downlink NAS Transport Message + err = liblte_s1ap_pack_s1ap_pdu(&tx_pdu, (LIBLTE_BYTE_MSG_STRUCT *) reply_msg); + if(err != LIBLTE_SUCCESS) + { + m_s1ap_log->console("Error packing Athentication Request"); + return false; + } //Send Reply to eNB ssize_t n_sent = sctp_send(m_s1mme,reply_msg->msg, reply_msg->N_bytes, enb_sri, 0); if(n_sent == -1) { - m_s1ap_log->console("Failed to send S1 Setup Setup Reply"); + m_s1ap_log->console("Failed to send NAS Attach Request"); return false; } - + m_s1ap_log->console("Sent NAS Athentication Request\n"); m_pool->deallocate(reply_msg); //TODO Start T3460 Timer! return true; From 961e0fc68d034fb1c3f068fa88ec9ea07ee06bf1 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 3 Nov 2017 11:02:30 +0000 Subject: [PATCH 047/172] Cleaning up the code --- srsepc/hdr/mme/s1ap_nas_transport.h | 11 +- srsepc/src/mme/s1ap.cc | 152 +++++------------------ srsepc/src/mme/s1ap_nas_transport.cc | 173 ++++++++++++++++++++++++++- 3 files changed, 207 insertions(+), 129 deletions(-) diff --git a/srsepc/hdr/mme/s1ap_nas_transport.h b/srsepc/hdr/mme/s1ap_nas_transport.h index db7c8c829..9d55b556e 100644 --- a/srsepc/hdr/mme/s1ap_nas_transport.h +++ b/srsepc/hdr/mme/s1ap_nas_transport.h @@ -27,7 +27,7 @@ #define S1AP_NAS_TRANSPORT_H #include "srslte/asn1/liblte_s1ap.h" -#include "srslte/common/common.h" +#include "srslte/common/buffer_pool.h" #include "mme/s1ap_common.h" namespace srsepc{ @@ -39,12 +39,17 @@ public: virtual ~s1ap_nas_transport(); void set_log(srslte::log *s1ap_logger); - bool unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, uint64_t *imsi); + bool unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req, LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req); bool pack_authentication_request(uint8_t *autn,uint8_t *rand); + void log_unhandled_attach_request_ies(const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req); + void log_unhandled_pdn_con_request_ies(const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req); + void log_unhandled_initial_ue_message_ies(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue); + + private: srslte::log *m_s1ap_log; - + srslte::byte_buffer_pool *m_pool; }; } //namespace srsepc diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 243e4c6b0..d89636f99 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -236,130 +236,43 @@ s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, st } bool -s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri) +s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, struct sctp_sndrcvinfo *enb_sri) { - m_s1ap_log->console("Received Initial UE Message\n"); - m_s1ap_log->info("Received Initial UE Message\n"); - - uint8_t amf[2]; // 3GPP 33.102 v10.0.0 Annex H - uint8_t op[16]; - uint8_t k[16]; - uint64_t imsi; - LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT attach_req; LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT pdn_con_req; - /*Get info from initial UE message*/ - uint32_t enb_ue_s1ap_id = msg->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; - /*Get NAS Attach Request Message*/ - uint8_t pd, msg_type; + uint64_t imsi; - srslte::byte_buffer_t *nas_msg = m_pool->allocate(); - memcpy(nas_msg->msg, &msg->NAS_PDU.buffer, msg->NAS_PDU.n_octets); - nas_msg->N_bytes = msg->NAS_PDU.n_octets; - liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &pd, &msg_type); - - if(msg_type!=LIBLTE_MME_MSG_TYPE_ATTACH_REQUEST){ - m_s1ap_log->error("Unhandled NAS message within the Initial UE message\n"); - return false; - } + uint8_t amf[2]; // 3GPP 33.102 v10.0.0 Annex H + uint8_t op[16]; + uint8_t k[16]; - LIBLTE_ERROR_ENUM err = liblte_mme_unpack_attach_request_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &attach_req); - if(err != LIBLTE_SUCCESS){ - m_s1ap_log->error("Error unpacking NAS attach request. Error: %s\n", liblte_error_text[err]); - return false; - } + /*Get info from initial UE message*/ + uint32_t enb_ue_s1ap_id = init_ue->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; + m_s1ap_log->console("Received Initial UE Message. eNB-UE S1AP Id: %d\n",enb_ue_s1ap_id); + m_s1ap_log->info("Received Initial UE Message. eNB-UE S1AP Id: %d\n",enb_ue_s1ap_id); - m_s1ap_log->info("Received Attach Request\n"); - if(attach_req.eps_mobile_id.type_of_id!=LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI){ - m_s1ap_log->error("NAS Attach Request: Unhandle UE Id Type"); - return false; - } - - imsi = 0; - for(int i=0;i<=14;i++) + /*Log unhandled Initial UE message IEs*/ + m_s1ap_nas_transport.log_unhandled_initial_ue_message_ies(init_ue); + + /*Get NAS Attach Request and PDN connectivity request messages*/ + if(!m_s1ap_nas_transport.unpack_initial_ue_message(init_ue, &attach_req,&pdn_con_req)) { + //TODO set up error reply + return false; + } + + //Get IMSI + imsi = 0; + for(int i=0;i<=14;i++){ imsi += attach_req.eps_mobile_id.imsi[i]*std::pow(10,14-i); } - m_s1ap_log->console("IMSI: %015lu\n", imsi); - - if(attach_req.old_p_tmsi_signature_present){} - if(attach_req.additional_guti_present){} - if(attach_req.last_visited_registered_tai_present){} - if(attach_req.drx_param_present){} - if(attach_req.ms_network_cap_present){} - if(attach_req.old_lai_present){} - if(attach_req.tmsi_status_present){} - if(attach_req.ms_cm2_present){} - if(attach_req.ms_cm3_present){} - if(attach_req.supported_codecs_present){} - if(attach_req.additional_update_type_present){} - if(attach_req.voice_domain_pref_and_ue_usage_setting_present){} - if(attach_req.device_properties_present){} - if(attach_req.old_guti_type_present){} + m_s1ap_log->console("Attach request from IMSI: %015lu\n", imsi); + m_s1ap_log->info("Attach request from IMSI: %015lu\n", imsi); - - /*Handle PDN Connctivity Request*/ - err = liblte_mme_unpack_pdn_connectivity_request_msg(&attach_req.esm_msg, &pdn_con_req); - if(err != LIBLTE_SUCCESS){ - m_s1ap_log->error("Error unpacking NAS PDN Connectivity Request. Error: %s\n", liblte_error_text[err]); - return false; - } - + //FIXME use this info uint8_t eps_bearer_id = pdn_con_req.eps_bearer_id; //TODO: Unused uint8_t proc_transaction_id = pdn_con_req.proc_transaction_id; //TODO: Transaction ID unused - if(pdn_con_req.pdn_type != LIBLTE_MME_PDN_TYPE_IPV4) - { - m_s1ap_log->error("PDN Connectivity Request: Only IPv4 connectivity supported.\n"); - return false; - } - if(pdn_con_req.request_type != LIBLTE_MME_REQUEST_TYPE_INITIAL_REQUEST) - { - m_s1ap_log->error("PDN Connectivity Request: Only Initial Request supported.\n"); - return false; - } - - //Handle the optional flags - if(pdn_con_req.esm_info_transfer_flag_present){} - if(pdn_con_req.apn_present){} - if(pdn_con_req.protocol_cnfg_opts_present){} - if(pdn_con_req.device_properties_present){} - - /*Log unhandled IEs*/ - if(msg->S_TMSI_present){ - m_s1ap_log->warning("S-TMSI present, but not handled."); - } - if(msg->CSG_Id_present){ - m_s1ap_log->warning("S-TMSI present, but not handled."); - } - if(msg->GUMMEI_ID_present){ - m_s1ap_log->warning("GUMMEI ID present, but not handled."); - } - if(msg->CellAccessMode_present){ - m_s1ap_log->warning("Cell Access Mode present, but not handled."); - } - if(msg->GW_TransportLayerAddress_present){ - m_s1ap_log->warning("GW Transport Layer present, but not handled."); - } - if(msg->GW_TransportLayerAddress_present){ - m_s1ap_log->warning("GW Transport Layer present, but not handled."); - } - if(msg->RelayNode_Indicator_present){ - m_s1ap_log->warning("Relay Node Indicator present, but not handled."); - } - if(msg->GUMMEIType_present){ - m_s1ap_log->warning("GUMMEI Type present, but not handled."); - } - if(msg->Tunnel_Information_for_BBF_present){ - m_s1ap_log->warning("Tunnel Information for BBF present, but not handled."); - } - if(msg->SIPTO_L_GW_TransportLayerAddress_present){ - m_s1ap_log->warning("SIPTO GW Transport Layer Address present, but not handled."); - } - if(msg->LHN_ID_present){ - m_s1ap_log->warning("LHN Id present, but not handled."); - } - uint8_t k_asme[32]; uint8_t autn[16]; @@ -393,19 +306,8 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = enb_ue_s1ap_id; dw_nas->HandoverRestrictionList_present=false; dw_nas->SubscriberProfileIDforRFP_present=false; - /* - typedef struct{ - bool ext; - LIBLTE_S1AP_MME_UE_S1AP_ID_STRUCT MME_UE_S1AP_ID; - LIBLTE_S1AP_ENB_UE_S1AP_ID_STRUCT eNB_UE_S1AP_ID; - LIBLTE_S1AP_NAS_PDU_STRUCT NAS_PDU; - LIBLTE_S1AP_HANDOVERRESTRICTIONLIST_STRUCT HandoverRestrictionList; - bool HandoverRestrictionList_present; - LIBLTE_S1AP_SUBSCRIBERPROFILEIDFORRFP_STRUCT SubscriberProfileIDforRFP; - bool SubscriberProfileIDforRFP_present; - }LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT; - */ - + + // LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT auth_req; memcpy(auth_req.autn , autn, 16); memcpy(auth_req.rand, rand, 16); @@ -415,7 +317,7 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg // Pack NAS_PDU nas_buffer = m_pool->allocate(); - err = liblte_mme_pack_authentication_request_msg(&auth_req, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + LIBLTE_ERROR_ENUM err = liblte_mme_pack_authentication_request_msg(&auth_req, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); if(err != LIBLTE_SUCCESS) { m_s1ap_log->console("Error packing Athentication Request"); diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index bf8a8d0a4..a5ac1e69d 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -31,6 +31,7 @@ namespace srsepc{ s1ap_nas_transport::s1ap_nas_transport() { + m_pool = srslte::byte_buffer_pool::get_instance(); return; } @@ -47,8 +48,53 @@ s1ap_nas_transport::set_log(srslte::log *s1ap_log) } bool -s1ap_nas_transport::unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, uint64_t *imsi) +s1ap_nas_transport::unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, + LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req, + LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req ) { + + /*Get NAS Attach Request Message*/ + uint8_t pd, msg_type; + srslte::byte_buffer_t *nas_msg = m_pool->allocate(); + + memcpy(nas_msg->msg, &init_ue->NAS_PDU.buffer, init_ue->NAS_PDU.n_octets); + nas_msg->N_bytes = init_ue->NAS_PDU.n_octets; + liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &pd, &msg_type); + + if(msg_type!=LIBLTE_MME_MSG_TYPE_ATTACH_REQUEST){ + m_s1ap_log->error("Unhandled NAS message within the Initial UE message\n"); + return false; + } + + LIBLTE_ERROR_ENUM err = liblte_mme_unpack_attach_request_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, attach_req); + if(err != LIBLTE_SUCCESS){ + m_s1ap_log->error("Error unpacking NAS attach request. Error: %s\n", liblte_error_text[err]); + return false; + } + /*Log unhandled Attach Request IEs*/ + log_unhandled_attach_request_ies(attach_req); + + /*Get PDN Connectivity Request*/ + err = liblte_mme_unpack_pdn_connectivity_request_msg(&attach_req->esm_msg, pdn_con_req); + if(err != LIBLTE_SUCCESS){ + m_s1ap_log->error("Error unpacking NAS PDN Connectivity Request. Error: %s\n", liblte_error_text[err]); + return false; + } + + if(pdn_con_req->pdn_type != LIBLTE_MME_PDN_TYPE_IPV4) + { + m_s1ap_log->error("PDN Connectivity Request: Only IPv4 connectivity supported.\n"); + return false; + } + if(pdn_con_req->request_type != LIBLTE_MME_REQUEST_TYPE_INITIAL_REQUEST) + { + m_s1ap_log->error("PDN Connectivity Request: Only Initial Request supported.\n"); + return false; + } + /*Log unhandled PDN connectivity request IEs*/ + log_unhandled_pdn_con_request_ies(pdn_con_req); + + m_pool->deallocate(nas_msg); return true; } @@ -65,4 +111,129 @@ s1ap_nas_transport::pack_authentication_request(uint8_t *autn,uint8_t *rand) return true; } +/*Helper functions*/ +void +s1ap_nas_transport::log_unhandled_attach_request_ies(const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req) +{ + if(attach_req->old_p_tmsi_signature_present) + { + m_s1ap_log->warning("NAS attach request: Old P-TMSI signature present, but not handled."); + } + if(attach_req->additional_guti_present) + { + m_s1ap_log->warning("NAS attach request: Aditional GUTI present, but not handled."); + } + if(attach_req->last_visited_registered_tai_present) + { + m_s1ap_log->warning("NAS attach request: Last visited registered TAI present, but not handled."); + } + if(attach_req->drx_param_present) + { + m_s1ap_log->warning("NAS attach request: DRX Param present, but not handled."); + } + if(attach_req->ms_network_cap_present) + { + m_s1ap_log->warning("NAS attach request: MS network cap present, but not handled."); + } + if(attach_req->old_lai_present) + { + m_s1ap_log->warning("NAS attach request: Old LAI present, but not handled."); + } + if(attach_req->tmsi_status_present) + { + m_s1ap_log->warning("NAS attach request: TSMI status present, but not handled."); + } + if(attach_req->ms_cm2_present) + { + m_s1ap_log->warning("NAS attach request: MS CM2 present, but not handled."); + } + if(attach_req->ms_cm3_present) + { + m_s1ap_log->warning("NAS attach request: MS CM3 present, but not handled."); + } + if(attach_req->supported_codecs_present) + { + m_s1ap_log->warning("NAS attach request: Supported CODECs present, but not handled."); + } + if(attach_req->additional_update_type_present) + { + m_s1ap_log->warning("NAS attach request: Additional Update Type present, but not handled."); + } + if(attach_req->voice_domain_pref_and_ue_usage_setting_present) + { + m_s1ap_log->warning("NAS attach request: Voice domain preference and UE usage setting present, but not handled."); + } + if(attach_req->device_properties_present) + { + m_s1ap_log->warning("NAS attach request: Device properties present, but not handled."); + } + if(attach_req->old_guti_type_present) + { + m_s1ap_log->warning("NAS attach request: Old GUTI type present, but not handled."); + } + return; +} + +void +s1ap_nas_transport::log_unhandled_pdn_con_request_ies(const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req) +{ + //Handle the optional flags + if(pdn_con_req->esm_info_transfer_flag_present) + { + m_s1ap_log->warning("PDN Connectivity request: ESM info transfer flag properties present, but not handled."); + } + if(pdn_con_req->apn_present) + { + m_s1ap_log->warning("PDN Connectivity request: APN present, but not handled."); + } + if(pdn_con_req->protocol_cnfg_opts_present) + { + m_s1ap_log->warning("PDN Connectivity request: Protocol Cnfg options present, but not handled."); + } + if(pdn_con_req->device_properties_present) + { + m_s1ap_log->warning("PDN Connectivity request: Device properties present, but not handled."); + } +} + + +void +s1ap_nas_transport::log_unhandled_initial_ue_message_ies(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue) +{ + if(init_ue->S_TMSI_present){ + m_s1ap_log->warning("S-TMSI present, but not handled."); + } + if(init_ue->CSG_Id_present){ + m_s1ap_log->warning("S-TMSI present, but not handled."); + } + if(init_ue->GUMMEI_ID_present){ + m_s1ap_log->warning("GUMMEI ID present, but not handled."); + } + if(init_ue->CellAccessMode_present){ + m_s1ap_log->warning("Cell Access Mode present, but not handled."); + } + if(init_ue->GW_TransportLayerAddress_present){ + m_s1ap_log->warning("GW Transport Layer present, but not handled."); + } + if(init_ue->GW_TransportLayerAddress_present){ + m_s1ap_log->warning("GW Transport Layer present, but not handled."); + } + if(init_ue->RelayNode_Indicator_present){ + m_s1ap_log->warning("Relay Node Indicator present, but not handled."); + } + if(init_ue->GUMMEIType_present){ + m_s1ap_log->warning("GUMMEI Type present, but not handled."); + } + if(init_ue->Tunnel_Information_for_BBF_present){ + m_s1ap_log->warning("Tunnel Information for BBF present, but not handled."); + } + if(init_ue->SIPTO_L_GW_TransportLayerAddress_present){ + m_s1ap_log->warning("SIPTO GW Transport Layer Address present, but not handled."); + } + if(init_ue->LHN_ID_present){ + m_s1ap_log->warning("LHN Id present, but not handled."); + } + return; +} + } //namespace srsepc From 5b5c65435dfd76b9eb5c2888f18ae3ff02fcede2 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 3 Nov 2017 14:38:34 +0000 Subject: [PATCH 048/172] Fixed bug in the packing of the dw nas message. UE receives the authentication request message now. --- srsepc/hdr/mme/s1ap_nas_transport.h | 2 +- srsepc/src/mme/s1ap.cc | 66 ++++------------------------ srsepc/src/mme/s1ap_nas_transport.cc | 57 +++++++++++++++++++++--- 3 files changed, 60 insertions(+), 65 deletions(-) diff --git a/srsepc/hdr/mme/s1ap_nas_transport.h b/srsepc/hdr/mme/s1ap_nas_transport.h index 9d55b556e..e9ed6da03 100644 --- a/srsepc/hdr/mme/s1ap_nas_transport.h +++ b/srsepc/hdr/mme/s1ap_nas_transport.h @@ -40,7 +40,7 @@ public: void set_log(srslte::log *s1ap_logger); bool unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req, LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req); - bool pack_authentication_request(uint8_t *autn,uint8_t *rand); + bool pack_authentication_request(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t next_mme_ue_s1ap_id, uint8_t *autn,uint8_t *rand); void log_unhandled_attach_request_ies(const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req); void log_unhandled_pdn_con_request_ies(const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req); diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index d89636f99..964626db5 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -33,7 +33,7 @@ namespace srsepc{ s1ap::s1ap(): m_s1mme(-1), - m_next_mme_ue_s1ap_id(0) + m_next_mme_ue_s1ap_id(1) { } @@ -242,10 +242,10 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT pdn_con_req; uint64_t imsi; - - uint8_t amf[2]; // 3GPP 33.102 v10.0.0 Annex H - uint8_t op[16]; - uint8_t k[16]; + uint8_t k_asme[32]; + uint8_t autn[16]; + uint8_t rand[6]; + uint8_t xres[16]; /*Get info from initial UE message*/ uint32_t enb_ue_s1ap_id = init_ue->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; @@ -274,67 +274,19 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini uint8_t eps_bearer_id = pdn_con_req.eps_bearer_id; //TODO: Unused uint8_t proc_transaction_id = pdn_con_req.proc_transaction_id; //TODO: Transaction ID unused - uint8_t k_asme[32]; - uint8_t autn[16]; - uint8_t rand[6]; - uint8_t xres[16]; - + //Get Authentication Vectors from HSS if(!m_hss->gen_auth_info_answer_milenage(imsi, k_asme, autn, rand, xres)) { m_s1ap_log->console("User not found. IMSI %015lu\n",imsi); m_s1ap_log->info("User not found. IMSI %015lu\n",imsi); return false; } - + + //Pack NAS Authentication Request in Downlink NAS Transport msg - srslte::byte_buffer_t *nas_buffer; srslte::byte_buffer_t *reply_msg = m_pool->allocate(); + m_s1ap_nas_transport.pack_authentication_request(reply_msg, enb_ue_s1ap_id, m_next_mme_ue_s1ap_id++, autn, rand); - //Setup initiating message - LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu; - tx_pdu.ext = false; - tx_pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE; - - LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *init = &tx_pdu.choice.initiatingMessage; - init->procedureCode = LIBLTE_S1AP_PROC_ID_DOWNLINKNASTRANSPORT; - init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DOWNLINKNASTRANSPORT; - - //Setup Dw NAS message - LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT *dw_nas = &init->choice.DownlinkNASTransport; - dw_nas->ext=false; - dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = m_next_mme_ue_s1ap_id++; - dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = enb_ue_s1ap_id; - dw_nas->HandoverRestrictionList_present=false; - dw_nas->SubscriberProfileIDforRFP_present=false; - - // - LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT auth_req; - memcpy(auth_req.autn , autn, 16); - memcpy(auth_req.rand, rand, 16); - auth_req.nas_ksi.tsc_flag=LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; - auth_req.nas_ksi.nas_ksi=0; - - - // Pack NAS_PDU - nas_buffer = m_pool->allocate(); - LIBLTE_ERROR_ENUM err = liblte_mme_pack_authentication_request_msg(&auth_req, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); - if(err != LIBLTE_SUCCESS) - { - m_s1ap_log->console("Error packing Athentication Request"); - return false; - } - - memcpy(dw_nas->NAS_PDU.buffer, nas_buffer->msg, nas_buffer->N_bytes); - dw_nas->NAS_PDU.n_octets = nas_buffer->N_bytes; - - //Pack Downlink NAS Transport Message - err = liblte_s1ap_pack_s1ap_pdu(&tx_pdu, (LIBLTE_BYTE_MSG_STRUCT *) reply_msg); - if(err != LIBLTE_SUCCESS) - { - m_s1ap_log->console("Error packing Athentication Request"); - return false; - } - //Send Reply to eNB ssize_t n_sent = sctp_send(m_s1mme,reply_msg->msg, reply_msg->N_bytes, enb_sri, 0); if(n_sent == -1) diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index a5ac1e69d..fbe90b8fd 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -99,15 +99,58 @@ s1ap_nas_transport::unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA } bool -s1ap_nas_transport::pack_authentication_request(uint8_t *autn,uint8_t *rand) +s1ap_nas_transport::pack_authentication_request(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t next_mme_ue_s1ap_id, uint8_t *autn, uint8_t *rand) { + srslte::byte_buffer_t *nas_buffer = m_pool->allocate(); + + //Setup initiating message + LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu; + bzero(&tx_pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); + + tx_pdu.ext = false; + tx_pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE; + + LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *init = &tx_pdu.choice.initiatingMessage; + init->procedureCode = LIBLTE_S1AP_PROC_ID_DOWNLINKNASTRANSPORT; + init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DOWNLINKNASTRANSPORT; + + //Setup Dw NAS structure + LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT *dw_nas = &init->choice.DownlinkNASTransport; + dw_nas->ext=false; + dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = next_mme_ue_s1ap_id; + dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = enb_ue_s1ap_id; + dw_nas->HandoverRestrictionList_present=false; + dw_nas->SubscriberProfileIDforRFP_present=false; + m_s1ap_log->console("Dw NAS id %d\n", enb_ue_s1ap_id); + + //Pack NAS PDU + LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT auth_req; + memcpy(auth_req.autn , autn, 16); + memcpy(auth_req.rand, rand, 16); + auth_req.nas_ksi.tsc_flag=LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; + auth_req.nas_ksi.nas_ksi=0; + + LIBLTE_ERROR_ENUM err = liblte_mme_pack_authentication_request_msg(&auth_req, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + if(err != LIBLTE_SUCCESS) + { + m_s1ap_log->console("Error packing Athentication Request\n"); + return false; + } + + //Copy NAS PDU to Downlink NAS Trasport message buffer + memcpy(dw_nas->NAS_PDU.buffer, nas_buffer->msg, nas_buffer->N_bytes); + dw_nas->NAS_PDU.n_octets = nas_buffer->N_bytes; + + //Pack Downlink NAS Transport Message + err = liblte_s1ap_pack_s1ap_pdu(&tx_pdu, (LIBLTE_BYTE_MSG_STRUCT *) reply_msg); + if(err != LIBLTE_SUCCESS) + { + m_s1ap_log->console("Error packing Athentication Request\n"); + return false; + } + + m_pool->deallocate(nas_buffer); - LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT pdu; - memcpy(pdu.autn , autn, 16); - memcpy(pdu.rand, rand, 16); - pdu.nas_ksi.tsc_flag=LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; - pdu.nas_ksi.nas_ksi=0; - return true; } From 25aa394086e7ecf358951bc1a41526a12708cfd1 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Sat, 4 Nov 2017 11:13:54 +0000 Subject: [PATCH 049/172] Adding some debug code. --- srsepc/src/hss/hss.cc | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index e5dc85b77..b41d8978b 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -37,7 +37,7 @@ hss* hss::m_instance = NULL; boost::mutex hss_instance_mutex; hss::hss() - :m_sqn(0) + :m_sqn(1) { m_pool = srslte::byte_buffer_pool::get_instance(); return; @@ -131,6 +131,18 @@ hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn mnc, k_asme); + //DEBUG code + std::cout<<"SQN: "; + for(int i=0;i<6;i++){ + std::cout << std::hex <<(uint16_t) sqn[i]; + } + std::cout< Date: Mon, 6 Nov 2017 15:41:14 +0000 Subject: [PATCH 050/172] Generating AUTN correctly. UE considers the network valid now. Starting to handle authentication response. --- srsepc/src/hss/hss.cc | 87 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 74 insertions(+), 13 deletions(-) diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index b41d8978b..64bf758bb 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -37,7 +37,7 @@ hss* hss::m_instance = NULL; boost::mutex hss_instance_mutex; hss::hss() - :m_sqn(1) + :m_sqn(0x112233445566) { m_pool = srslte::byte_buffer_pool::get_instance(); return; @@ -97,8 +97,8 @@ hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn uint8_t ak[6]; uint8_t mac[8]; - uint16_t mcc=1; - uint16_t mnc=1; + uint16_t mcc=61441; //001 + uint16_t mnc=65281; //01 if(!get_k_amf_op(imsi,k,amf,op)) { @@ -131,10 +131,40 @@ hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn mnc, k_asme); + //Generate AUTN (autn = sqn ^ ak |+| amf |+| mac) + for(int i=0;i<6;i++ ) + { + autn[i] = sqn[i]^ak[i]; + } + for(int i=0;i<2;i++) + { + autn[6+i]=amf[i]; + } + for(int i=0;i<8;i++) + { + autn[8+i]=mac[i]; + } + + std::cout<<"IMSI: "<< imsi << std::endl; + std::cout<<"MCC: "< Date: Mon, 6 Nov 2017 15:42:08 +0000 Subject: [PATCH 051/172] deleting debug code --- srsepc/src/hss/hss.cc | 66 ------------------------------------------- 1 file changed, 66 deletions(-) diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index 64bf758bb..ccc1c3971 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -145,72 +145,6 @@ hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn autn[8+i]=mac[i]; } - std::cout<<"IMSI: "<< imsi << std::endl; - std::cout<<"MCC: "< Date: Mon, 6 Nov 2017 17:03:26 +0000 Subject: [PATCH 052/172] Starting to parse UL NAS Transport --- srsepc/hdr/mme/s1ap.h | 4 +++- srsepc/src/mme/s1ap.cc | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 2ab1d74c1..3e16cc2f8 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -68,8 +68,10 @@ public: bool send_s1_setup_response(struct sctp_sndrcvinfo *enb_sri); - bool handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri); + bool handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, struct sctp_sndrcvinfo *enb_sri); + bool handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, struct sctp_sndrcvinfo *enb_sri); + void print_enb_ctx_info(const enb_ctx_t &enb_ctx); private: diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 964626db5..fa88d347d 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -171,6 +171,9 @@ s1ap::handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, stru case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_INITIALUEMESSAGE: m_s1ap_log->info("Received Initial UE Message.\n"); return handle_initial_ue_message(&msg->choice.InitialUEMessage, enb_sri); + case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UPLINKNASTRANSPORT: + m_s1ap_log->info("Received Initial UE Message.\n"); + return handle_uplink_nas_transport(&msg->choice.UplinkNASTransport, enb_sri); default: m_s1ap_log->error("Unhandled intiating message: %s\n", liblte_s1ap_initiatingmessage_choice_text[msg->choice_type]); } @@ -300,8 +303,37 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini return true; } +bool +s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, struct sctp_sndrcvinfo *enb_sri) +{ + uint32_t enb_ue_s1ap_id = ul_xport->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; + uint32_t mme_ue_s1ap_id = ul_xport->MME_UE_S1AP_ID.MME_UE_S1AP_ID; + m_s1ap_log->console("Received Uplink NAS Transport message. MME-UE S1AP Id: %d\n",mme_ue_s1ap_id); + m_s1ap_log->info("Received Uplink NAS Transport message. MME-UE S1AP Id: %d\n",mme_ue_s1ap_id); + + /* + typedef struct{ + bool ext; + LIBLTE_S1AP_MME_UE_S1AP_ID_STRUCT MME_UE_S1AP_ID; + LIBLTE_S1AP_ENB_UE_S1AP_ID_STRUCT eNB_UE_S1AP_ID; + LIBLTE_S1AP_NAS_PDU_STRUCT NAS_PDU; + LIBLTE_S1AP_EUTRAN_CGI_STRUCT EUTRAN_CGI; + LIBLTE_S1AP_TAI_STRUCT TAI; + LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT GW_TransportLayerAddress; + bool GW_TransportLayerAddress_present; + LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT SIPTO_L_GW_TransportLayerAddress; + bool SIPTO_L_GW_TransportLayerAddress_present; + LIBLTE_S1AP_LHN_ID_STRUCT LHN_ID; + bool LHN_ID_present; + }LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT; + */ + + //m_s1ap_nas_transport.log_unhandled_uplink_nas_transport_message_ies(ul_xport); + + return true; +} void s1ap::print_enb_ctx_info(const enb_ctx_t &enb_ctx) { From 44a28b3302f39222aad451aa1fb667c10580472c Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 6 Nov 2017 19:10:57 +0000 Subject: [PATCH 053/172] Starting to save UE context. --- srsepc/hdr/mme/s1ap.h | 18 +++++----- srsepc/hdr/mme/s1ap_common.h | 7 ++++ srsepc/hdr/mme/s1ap_nas_transport.h | 1 + srsepc/src/mme/s1ap.cc | 50 ++++++++++++++++++++++++---- srsepc/src/mme/s1ap_nas_transport.cc | 32 ++++++++++++++++++ 5 files changed, 94 insertions(+), 14 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 3e16cc2f8..2887938da 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -76,18 +76,20 @@ public: private: - s1ap_args_t m_s1ap_args; - uint32_t m_plmn; - srslte::byte_buffer_pool *m_pool; - srslte::log *m_s1ap_log; + s1ap_args_t m_s1ap_args; + uint32_t m_plmn; + srslte::byte_buffer_pool *m_pool; + srslte::log *m_s1ap_log; hss *m_hss; int m_s1mme; - std::map m_active_enbs; - uint32_t m_next_mme_ue_s1ap_id; + std::map m_active_enbs; + std::map m_active_ues; + + uint32_t m_next_mme_ue_s1ap_id; - s1ap_mngmt_proc m_s1ap_mngmt_proc; - s1ap_nas_transport m_s1ap_nas_transport; + s1ap_mngmt_proc m_s1ap_mngmt_proc; + s1ap_nas_transport m_s1ap_nas_transport; }; diff --git a/srsepc/hdr/mme/s1ap_common.h b/srsepc/hdr/mme/s1ap_common.h index 4d76570f9..6190461e5 100644 --- a/srsepc/hdr/mme/s1ap_common.h +++ b/srsepc/hdr/mme/s1ap_common.h @@ -48,4 +48,11 @@ typedef struct{ struct sctp_sndrcvinfo sri; } enb_ctx_t; +typedef struct{ + uint64_t imsi; + uint32_t enb_ue_s1ap_id; + uint32_t mme_ue_s1ap_id; + uint8_t xres[16]; +} ue_ctx_t; + #endif diff --git a/srsepc/hdr/mme/s1ap_nas_transport.h b/srsepc/hdr/mme/s1ap_nas_transport.h index e9ed6da03..940250ac7 100644 --- a/srsepc/hdr/mme/s1ap_nas_transport.h +++ b/srsepc/hdr/mme/s1ap_nas_transport.h @@ -41,6 +41,7 @@ public: void set_log(srslte::log *s1ap_logger); bool unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req, LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req); bool pack_authentication_request(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t next_mme_ue_s1ap_id, uint8_t *autn,uint8_t *rand); + bool unpack_authentication_response(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT *auth_resp); void log_unhandled_attach_request_ies(const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req); void log_unhandled_pdn_con_request_ies(const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req); diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index fa88d347d..dba211d19 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -250,10 +250,12 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini uint8_t rand[6]; uint8_t xres[16]; + ue_ctx_t ue_ctx; + /*Get info from initial UE message*/ - uint32_t enb_ue_s1ap_id = init_ue->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; - m_s1ap_log->console("Received Initial UE Message. eNB-UE S1AP Id: %d\n",enb_ue_s1ap_id); - m_s1ap_log->info("Received Initial UE Message. eNB-UE S1AP Id: %d\n",enb_ue_s1ap_id); + ue_ctx.enb_ue_s1ap_id = init_ue->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; + m_s1ap_log->console("Received Initial UE Message. eNB-UE S1AP Id: %d\n", ue_ctx.enb_ue_s1ap_id); + m_s1ap_log->info("Received Initial UE Message. eNB-UE S1AP Id: %d\n", ue_ctx.enb_ue_s1ap_id); /*Log unhandled Initial UE message IEs*/ m_s1ap_nas_transport.log_unhandled_initial_ue_message_ies(init_ue); @@ -278,17 +280,24 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini uint8_t proc_transaction_id = pdn_con_req.proc_transaction_id; //TODO: Transaction ID unused //Get Authentication Vectors from HSS - if(!m_hss->gen_auth_info_answer_milenage(imsi, k_asme, autn, rand, xres)) + if(!m_hss->gen_auth_info_answer_milenage(imsi, k_asme, autn, rand, ue_ctx.xres)) { m_s1ap_log->console("User not found. IMSI %015lu\n",imsi); m_s1ap_log->info("User not found. IMSI %015lu\n",imsi); return false; } - + + //Save UE context + ue_ctx.imsi = imsi; + ue_ctx.mme_ue_s1ap_id = m_next_mme_ue_s1ap_id++; + + ue_ctx_t *ue_ptr = new ue_ctx_t;//TODO use buffer pool here? + memcpy(ue_ptr,&ue_ctx,sizeof(ue_ctx)); + m_active_ues.insert(std::pair(ue_ptr->mme_ue_s1ap_id,ue_ptr)); //Pack NAS Authentication Request in Downlink NAS Transport msg srslte::byte_buffer_t *reply_msg = m_pool->allocate(); - m_s1ap_nas_transport.pack_authentication_request(reply_msg, enb_ue_s1ap_id, m_next_mme_ue_s1ap_id++, autn, rand); + m_s1ap_nas_transport.pack_authentication_request(reply_msg, ue_ctx.enb_ue_s1ap_id, ue_ctx.mme_ue_s1ap_id, autn, rand); //Send Reply to eNB ssize_t n_sent = sctp_send(m_s1mme,reply_msg->msg, reply_msg->N_bytes, enb_sri, 0); @@ -307,12 +316,36 @@ bool s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, struct sctp_sndrcvinfo *enb_sri) { + bool ue_valid = true; uint32_t enb_ue_s1ap_id = ul_xport->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; uint32_t mme_ue_s1ap_id = ul_xport->MME_UE_S1AP_ID.MME_UE_S1AP_ID; + LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT auth_resp; + m_s1ap_log->console("Received Uplink NAS Transport message. MME-UE S1AP Id: %d\n",mme_ue_s1ap_id); m_s1ap_log->info("Received Uplink NAS Transport message. MME-UE S1AP Id: %d\n",mme_ue_s1ap_id); + //mme_ue_ctx_t ue_ctx = m_mme_ue_map[mme_ue_s1ap_id]; + //if(mme_ue_ctx == m_mme_ue_map.end()) + //{ + // + //} + + //Get NAS authentication response + if(!m_s1ap_nas_transport.unpack_authentication_response(ul_xport, &auth_resp)) + { + //TODO set up error reply + return false; + } + + //for(int i=0; i<16;i++) + //{ + // if(auth_resp.res[i] != ue_ctx.xres[i]) + // { + // ue_valid = false; + // } + //} + /* typedef struct{ bool ext; @@ -329,6 +362,11 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT bool LHN_ID_present; }LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT; */ + /* + typedef struct{ + uint8 res[16]; + }LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT; + */ //m_s1ap_nas_transport.log_unhandled_uplink_nas_transport_message_ies(ul_xport); diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index fbe90b8fd..36853d145 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -154,6 +154,35 @@ s1ap_nas_transport::pack_authentication_request(srslte::byte_buffer_t *reply_msg return true; } +bool +s1ap_nas_transport::unpack_authentication_response(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, + LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT *auth_resp ) +{ + + /*Get NAS Authentiation Response Message*/ + uint8_t pd, msg_type; + srslte::byte_buffer_t *nas_msg = m_pool->allocate(); + + memcpy(nas_msg->msg, &ul_xport->NAS_PDU.buffer, ul_xport->NAS_PDU.n_octets); + nas_msg->N_bytes = ul_xport->NAS_PDU.n_octets; + liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &pd, &msg_type); + + if(msg_type!=LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE){ + m_s1ap_log->error("Unhandled NAS message within UL NAS Transport message\n"); + return false; + } + + LIBLTE_ERROR_ENUM err = liblte_mme_unpack_authentication_response_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, auth_resp); + if(err != LIBLTE_SUCCESS){ + m_s1ap_log->error("Error unpacking NAS authentication response. Error: %s\n", liblte_error_text[err]); + return false; + } + + m_pool->deallocate(nas_msg); + return true; +} + + /*Helper functions*/ void s1ap_nas_transport::log_unhandled_attach_request_ies(const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req) @@ -279,4 +308,7 @@ s1ap_nas_transport::log_unhandled_initial_ue_message_ies(LIBLTE_S1AP_MESSAGE_INI return; } + + + } //namespace srsepc From d5e1290883e5b3d2aa0d83a471e6af492eb2984b Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 7 Nov 2017 14:13:09 +0000 Subject: [PATCH 054/172] starting to work on the security mode command --- srsepc/src/mme/s1ap.cc | 52 +++++++++++---- srsepc/src/mme/s1ap_nas_transport.cc | 99 +++++++++++++++++++++++++++- 2 files changed, 137 insertions(+), 14 deletions(-) diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index dba211d19..992ab5f3a 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -319,17 +319,21 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT bool ue_valid = true; uint32_t enb_ue_s1ap_id = ul_xport->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; uint32_t mme_ue_s1ap_id = ul_xport->MME_UE_S1AP_ID.MME_UE_S1AP_ID; + ue_ctx_t *ue_ctx; LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT auth_resp; + srslte::byte_buffer_t *reply_msg = m_pool->allocate(); m_s1ap_log->console("Received Uplink NAS Transport message. MME-UE S1AP Id: %d\n",mme_ue_s1ap_id); m_s1ap_log->info("Received Uplink NAS Transport message. MME-UE S1AP Id: %d\n",mme_ue_s1ap_id); - //mme_ue_ctx_t ue_ctx = m_mme_ue_map[mme_ue_s1ap_id]; - //if(mme_ue_ctx == m_mme_ue_map.end()) - //{ - // - //} + std::map::iterator it = m_active_ues.find(mme_ue_s1ap_id); + ue_ctx = it->second; + if(it == m_active_ues.end()) + { + //TODO UE not registered, send error message. + return false; + } //Get NAS authentication response if(!m_s1ap_nas_transport.unpack_authentication_response(ul_xport, &auth_resp)) @@ -338,13 +342,23 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT return false; } - //for(int i=0; i<16;i++) - //{ - // if(auth_resp.res[i] != ue_ctx.xres[i]) - // { - // ue_valid = false; - // } - //} + for(int i=0; i<16;i++) + { + if(auth_resp.res[i] != ue_ctx->xres[i]) + { + ue_valid = false; + } + } + if(!ue_valid) + { + m_s1ap_log->warning("UE Authentication Rejected. IMSI: %lu\n", ue_ctx->imsi); + //TODO send back error reply + return false; + } + m_s1ap_log->console("UE Authentication Accepted. IMSI: %lu\n", ue_ctx->imsi); + + + m_s1ap_nas_transport.pack_security_mode_command(); /* typedef struct{ @@ -368,6 +382,20 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT }LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT; */ + /* + typedef struct{ + LIBLTE_MME_NAS_SECURITY_ALGORITHMS_STRUCT selected_nas_sec_algs; + LIBLTE_MME_NAS_KEY_SET_ID_STRUCT nas_ksi; + LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT ue_security_cap; + LIBLTE_MME_IMEISV_REQUEST_ENUM imeisv_req; + uint32 nonce_ue; + uint32 nonce_mme; + bool imeisv_req_present; + bool nonce_ue_present; + bool nonce_mme_present; + }LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT; + */ + //m_s1ap_nas_transport.log_unhandled_uplink_nas_transport_message_ies(ul_xport); return true; diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 36853d145..4c61533dd 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -182,10 +182,105 @@ s1ap_nas_transport::unpack_authentication_response(LIBLTE_S1AP_MESSAGE_UPLINKNAS return true; } +s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t reply_msg, mme_ue_ctx_t *ue_ctx) +{ + srslte::byte_buffer_t *nas_buffer = m_pool->allocate(); + + //Setup initiating message + LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu; + bzero(&tx_pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); + + tx_pdu.ext = false; + tx_pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE; + + LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *init = &tx_pdu.choice.initiatingMessage; + init->procedureCode = LIBLTE_S1AP_PROC_ID_DOWNLINKNASTRANSPORT; + init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DOWNLINKNASTRANSPORT; + + //Setup Dw NAS structure + LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT *dw_nas = &init->choice.DownlinkNASTransport; + dw_nas->ext=false; + dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = ue_ctx->mme_ue_s1ap_id; + dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ue_ctx->enb_ue_s1ap_id; + dw_nas->HandoverRestrictionList_present=false; + dw_nas->SubscriberProfileIDforRFP_present=false; + m_s1ap_log->console("Dw NAS id %d\n", ue_ctx->enb_ue_s1ap_id); + + //Pack NAS PDU + LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT sm_cmd; + + sm_cmd.selected_nas_sec_algs; + sm_cmd.nas_ksi.tsc_flag=LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; + sm_cmd.nas_ksi.nas_ksi=0; + + LIBLTE_ERROR_ENUM err = liblte_mme_pack_security_mode_command_msg(&sm_cmd, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + if(err != LIBLTE_SUCCESS) + { + m_s1ap_log->console("Error packing Athentication Request\n"); + return false; + } + + //Copy NAS PDU to Downlink NAS Trasport message buffer + memcpy(dw_nas->NAS_PDU.buffer, nas_buffer->msg, nas_buffer->N_bytes); + dw_nas->NAS_PDU.n_octets = nas_buffer->N_bytes; + + //Pack Downlink NAS Transport Message + err = liblte_s1ap_pack_s1ap_pdu(&tx_pdu, (LIBLTE_BYTE_MSG_STRUCT *) reply_msg); + if(err != LIBLTE_SUCCESS) + { + m_s1ap_log->console("Error packing Athentication Request\n"); + return false; + } + + m_pool->deallocate(nas_buffer); + + return true; +} + + + /* + typedef struct{ + LIBLTE_MME_NAS_SECURITY_ALGORITHMS_STRUCT selected_nas_sec_algs; + LIBLTE_MME_NAS_KEY_SET_ID_STRUCT nas_ksi; + LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT ue_security_cap; + LIBLTE_MME_IMEISV_REQUEST_ENUM imeisv_req; + uint32 nonce_ue; + uint32 nonce_mme; + bool imeisv_req_present; + bool nonce_ue_present; + bool nonce_mme_present; + }LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT; + */ + /* + typedef struct{ + LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_ENUM type_of_eea; + LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_ENUM type_of_eia; + }LIBLTE_MME_NAS_SECURITY_ALGORITHMS_STRUCT; + */ + /* + typedef struct{ + LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_ENUM tsc_flag; + uint8 nas_ksi; + }LIBLTE_MME_NAS_KEY_SET_ID_STRUCT; + */ + /* + typedef struct{ + bool eea[8]; + bool eia[8]; + bool uea[8]; + bool uea_present; + bool uia[8]; + bool uia_present; + bool gea[8]; + bool gea_present; + }LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT; + */ + +} /*Helper functions*/ -void -s1ap_nas_transport::log_unhandled_attach_request_ies(const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req) + +voi::log_unhandled_attach_request_ies(const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req) { if(attach_req->old_p_tmsi_signature_present) { From dc107edd419e805ab6e831152fdfe5a9a0ce7cf0 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 7 Nov 2017 15:10:52 +0000 Subject: [PATCH 055/172] Continue to pack security mode command --- srsepc/hdr/mme/s1ap_nas_transport.h | 1 + srsepc/src/mme/s1ap.cc | 32 ++++++++++++-- srsepc/src/mme/s1ap_nas_transport.cc | 62 ++++++++-------------------- 3 files changed, 48 insertions(+), 47 deletions(-) diff --git a/srsepc/hdr/mme/s1ap_nas_transport.h b/srsepc/hdr/mme/s1ap_nas_transport.h index 940250ac7..03444cee7 100644 --- a/srsepc/hdr/mme/s1ap_nas_transport.h +++ b/srsepc/hdr/mme/s1ap_nas_transport.h @@ -42,6 +42,7 @@ public: bool unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req, LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req); bool pack_authentication_request(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t next_mme_ue_s1ap_id, uint8_t *autn,uint8_t *rand); bool unpack_authentication_response(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT *auth_resp); + bool pack_security_mode_command(srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx); void log_unhandled_attach_request_ies(const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req); void log_unhandled_pdn_con_request_ies(const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req); diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 992ab5f3a..243f42ef7 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -322,7 +322,7 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT ue_ctx_t *ue_ctx; LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT auth_resp; - srslte::byte_buffer_t *reply_msg = m_pool->allocate(); + srslte::byte_buffer_t *reply_msg; m_s1ap_log->console("Received Uplink NAS Transport message. MME-UE S1AP Id: %d\n",mme_ue_s1ap_id); m_s1ap_log->info("Received Uplink NAS Transport message. MME-UE S1AP Id: %d\n",mme_ue_s1ap_id); @@ -357,8 +357,9 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT } m_s1ap_log->console("UE Authentication Accepted. IMSI: %lu\n", ue_ctx->imsi); - - m_s1ap_nas_transport.pack_security_mode_command(); + reply_msg = m_pool->allocate(); + + m_s1ap_nas_transport.pack_security_mode_command(reply_msg, ue_ctx); /* typedef struct{ @@ -395,6 +396,31 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT bool nonce_mme_present; }LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT; */ + /* + typedef struct{ + LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_ENUM type_of_eea; + LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_ENUM type_of_eia; + }LIBLTE_MME_NAS_SECURITY_ALGORITHMS_STRUCT; + */ + /* + typedef struct{ + LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_ENUM tsc_flag; + uint8 nas_ksi; + }LIBLTE_MME_NAS_KEY_SET_ID_STRUCT; + */ + /* + typedef struct{ + bool eea[8]; + bool eia[8]; + bool uea[8]; + bool uea_present; + bool uia[8]; + bool uia_present; + bool gea[8]; + bool gea_present; + }LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT; + */ + //m_s1ap_nas_transport.log_unhandled_uplink_nas_transport_message_ies(ul_xport); diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 4c61533dd..c1f5dca26 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -182,7 +182,8 @@ s1ap_nas_transport::unpack_authentication_response(LIBLTE_S1AP_MESSAGE_UPLINKNAS return true; } -s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t reply_msg, mme_ue_ctx_t *ue_ctx) +bool +s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx) { srslte::byte_buffer_t *nas_buffer = m_pool->allocate(); @@ -209,11 +210,23 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t reply_msg, //Pack NAS PDU LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT sm_cmd; - sm_cmd.selected_nas_sec_algs; + sm_cmd.selected_nas_sec_algs.type_of_eea = LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_EEA0; + sm_cmd.selected_nas_sec_algs.type_of_eia = LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_EIA0; + sm_cmd.nas_ksi.tsc_flag=LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; sm_cmd.nas_ksi.nas_ksi=0; - LIBLTE_ERROR_ENUM err = liblte_mme_pack_security_mode_command_msg(&sm_cmd, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + //FIXME UE security cap not used by srsUE. + //sm_cmd.ue_security_cap; + + sm_cmd.imeisv_req_present=false; + sm_cmd.nonce_ue_present=false; + sm_cmd.nonce_mme_present=false; + + uint8_t sec_hdr_type; + uint32_t count; + + LIBLTE_ERROR_ENUM err = liblte_mme_pack_security_mode_command_msg(&sm_cmd,sec_hdr_type, count,(LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); if(err != LIBLTE_SUCCESS) { m_s1ap_log->console("Error packing Athentication Request\n"); @@ -238,49 +251,10 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t reply_msg, } - /* - typedef struct{ - LIBLTE_MME_NAS_SECURITY_ALGORITHMS_STRUCT selected_nas_sec_algs; - LIBLTE_MME_NAS_KEY_SET_ID_STRUCT nas_ksi; - LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT ue_security_cap; - LIBLTE_MME_IMEISV_REQUEST_ENUM imeisv_req; - uint32 nonce_ue; - uint32 nonce_mme; - bool imeisv_req_present; - bool nonce_ue_present; - bool nonce_mme_present; - }LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT; - */ - /* - typedef struct{ - LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_ENUM type_of_eea; - LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_ENUM type_of_eia; - }LIBLTE_MME_NAS_SECURITY_ALGORITHMS_STRUCT; - */ - /* - typedef struct{ - LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_ENUM tsc_flag; - uint8 nas_ksi; - }LIBLTE_MME_NAS_KEY_SET_ID_STRUCT; - */ - /* - typedef struct{ - bool eea[8]; - bool eia[8]; - bool uea[8]; - bool uea_present; - bool uia[8]; - bool uia_present; - bool gea[8]; - bool gea_present; - }LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT; - */ - -} /*Helper functions*/ - -voi::log_unhandled_attach_request_ies(const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req) +void +s1ap_nas_transport::log_unhandled_attach_request_ies(const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req) { if(attach_req->old_p_tmsi_signature_present) { From bb85525ad22fa61f7e69e5a3bb4c8e2215fa818e Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 7 Nov 2017 18:04:10 +0000 Subject: [PATCH 056/172] Fixed bug on network authentication. --- srsepc/src/hss/hss.cc | 25 ++++++++ srsepc/src/mme/s1ap.cc | 91 ++++++++-------------------- srsepc/src/mme/s1ap_nas_transport.cc | 10 +-- 3 files changed, 55 insertions(+), 71 deletions(-) diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index ccc1c3971..4a21f2614 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -25,6 +25,8 @@ */ #include /* srand, rand */ #include /* time */ +#include +#include #include #include "hss/hss.h" #include "srslte/common/security.h" @@ -145,6 +147,29 @@ hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn autn[8+i]=mac[i]; } + + + //std::stringstream ss; + std::cout<<"SQN: "; + for(int i=0;i<6;i++) + { + std::cout << std::hex <<(uint16_t)sqn[i]; + } + std::cout<console("Could not find UE. MME-UE S1AP id: %lu\n",mme_ue_s1ap_id); return false; } + m_s1ap_log->console("Found UE. MME-UE S1AP id: %lu",mme_ue_s1ap_id); //Get NAS authentication response if(!m_s1ap_nas_transport.unpack_authentication_response(ul_xport, &auth_resp)) { - //TODO set up error reply + m_s1ap_log->warning("Error unpacking authentication response\n"); return false; } - for(int i=0; i<16;i++) + for(int i=0; i<8;i++) { if(auth_resp.res[i] != ue_ctx->xres[i]) { @@ -351,78 +353,35 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT } if(!ue_valid) { + std::cout<xres[i]; + } + std::cout<console("UE Authentication Rejected. IMSI: %lu\n", ue_ctx->imsi); m_s1ap_log->warning("UE Authentication Rejected. IMSI: %lu\n", ue_ctx->imsi); //TODO send back error reply return false; } m_s1ap_log->console("UE Authentication Accepted. IMSI: %lu\n", ue_ctx->imsi); - reply_msg = m_pool->allocate(); + //Send Security Mode Command + reply_msg = m_pool->allocate(); m_s1ap_nas_transport.pack_security_mode_command(reply_msg, ue_ctx); - /* - typedef struct{ - bool ext; - LIBLTE_S1AP_MME_UE_S1AP_ID_STRUCT MME_UE_S1AP_ID; - LIBLTE_S1AP_ENB_UE_S1AP_ID_STRUCT eNB_UE_S1AP_ID; - LIBLTE_S1AP_NAS_PDU_STRUCT NAS_PDU; - LIBLTE_S1AP_EUTRAN_CGI_STRUCT EUTRAN_CGI; - LIBLTE_S1AP_TAI_STRUCT TAI; - LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT GW_TransportLayerAddress; - bool GW_TransportLayerAddress_present; - LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT SIPTO_L_GW_TransportLayerAddress; - bool SIPTO_L_GW_TransportLayerAddress_present; - LIBLTE_S1AP_LHN_ID_STRUCT LHN_ID; - bool LHN_ID_present; - }LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT; - */ - /* - typedef struct{ - uint8 res[16]; - }LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT; - */ - - /* - typedef struct{ - LIBLTE_MME_NAS_SECURITY_ALGORITHMS_STRUCT selected_nas_sec_algs; - LIBLTE_MME_NAS_KEY_SET_ID_STRUCT nas_ksi; - LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT ue_security_cap; - LIBLTE_MME_IMEISV_REQUEST_ENUM imeisv_req; - uint32 nonce_ue; - uint32 nonce_mme; - bool imeisv_req_present; - bool nonce_ue_present; - bool nonce_mme_present; - }LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT; - */ - /* - typedef struct{ - LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_ENUM type_of_eea; - LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_ENUM type_of_eia; - }LIBLTE_MME_NAS_SECURITY_ALGORITHMS_STRUCT; - */ - /* - typedef struct{ - LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_ENUM tsc_flag; - uint8 nas_ksi; - }LIBLTE_MME_NAS_KEY_SET_ID_STRUCT; - */ - /* - typedef struct{ - bool eea[8]; - bool eia[8]; - bool uea[8]; - bool uea_present; - bool uia[8]; - bool uia_present; - bool gea[8]; - bool gea_present; - }LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT; - */ - - - //m_s1ap_nas_transport.log_unhandled_uplink_nas_transport_message_ies(ul_xport); + //Send Reply to eNB + ssize_t n_sent = sctp_send(m_s1mme,reply_msg->msg, reply_msg->N_bytes, enb_sri, 0); + if(n_sent == -1) + { + m_s1ap_log->console("Failed to send NAS Attach Request"); + return false; + } + m_s1ap_log->console("Sent Security Mode Command\n"); + m_pool->deallocate(reply_msg); return true; } diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index c1f5dca26..d9b8f5e25 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -205,13 +205,13 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ue_ctx->enb_ue_s1ap_id; dw_nas->HandoverRestrictionList_present=false; dw_nas->SubscriberProfileIDforRFP_present=false; - m_s1ap_log->console("Dw NAS id %d\n", ue_ctx->enb_ue_s1ap_id); + m_s1ap_log->console("Sending Security Mode command to MME-UE S1AP Id %d\n", ue_ctx->mme_ue_s1ap_id); //Pack NAS PDU LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT sm_cmd; sm_cmd.selected_nas_sec_algs.type_of_eea = LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_EEA0; - sm_cmd.selected_nas_sec_algs.type_of_eia = LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_EIA0; + sm_cmd.selected_nas_sec_algs.type_of_eia = LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_128_EIA1; sm_cmd.nas_ksi.tsc_flag=LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; sm_cmd.nas_ksi.nas_ksi=0; @@ -219,12 +219,12 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, //FIXME UE security cap not used by srsUE. //sm_cmd.ue_security_cap; - sm_cmd.imeisv_req_present=false; + sm_cmd.imeisv_req_present=false; sm_cmd.nonce_ue_present=false; sm_cmd.nonce_mme_present=false; - uint8_t sec_hdr_type; - uint32_t count; + uint8_t sec_hdr_type=3; + uint32_t count=0; LIBLTE_ERROR_ENUM err = liblte_mme_pack_security_mode_command_msg(&sm_cmd,sec_hdr_type, count,(LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); if(err != LIBLTE_SUCCESS) From 1621b6e93a7105ca8745a6acb5857df0be5ad1f5 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 7 Nov 2017 20:14:43 +0000 Subject: [PATCH 057/172] Starting to integrity protect NAS messages. UE accepted security command reques, starting to parse security command complete. --- srsepc/hdr/mme/s1ap_common.h | 3 ++- srsepc/src/mme/s1ap.cc | 3 ++- srsepc/src/mme/s1ap_nas_transport.cc | 26 ++++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/srsepc/hdr/mme/s1ap_common.h b/srsepc/hdr/mme/s1ap_common.h index 6190461e5..496518ca0 100644 --- a/srsepc/hdr/mme/s1ap_common.h +++ b/srsepc/hdr/mme/s1ap_common.h @@ -52,7 +52,8 @@ typedef struct{ uint64_t imsi; uint32_t enb_ue_s1ap_id; uint32_t mme_ue_s1ap_id; - uint8_t xres[16]; + uint8_t xres[8]; + uint8_t k_asme[32]; } ue_ctx_t; #endif diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 699e602d4..89b0a24f0 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -278,9 +278,10 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini //FIXME use this info uint8_t eps_bearer_id = pdn_con_req.eps_bearer_id; //TODO: Unused uint8_t proc_transaction_id = pdn_con_req.proc_transaction_id; //TODO: Transaction ID unused + m_s1ap_log->console("EPS Bearer id: %d\n", eps_bearer_id); //Get Authentication Vectors from HSS - if(!m_hss->gen_auth_info_answer_milenage(imsi, k_asme, autn, rand, ue_ctx.xres)) + if(!m_hss->gen_auth_info_answer_milenage(imsi, ue_ctx.k_asme, autn, rand, ue_ctx.xres)) { m_s1ap_log->console("User not found. IMSI %015lu\n",imsi); m_s1ap_log->info("User not found. IMSI %015lu\n",imsi); diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index d9b8f5e25..d2212ad2f 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -26,6 +26,7 @@ #include "mme/s1ap.h" #include "mme/s1ap_nas_transport.h" +#include "srslte/common/security.h" namespace srsepc{ @@ -233,6 +234,31 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, return false; } + //Generate MAC for integrity protection + //FIXME Write wrapper to support EIA1, EIA2, etc. + //TODO which is the RB ID? Standard says a constant, but which? + uint8_t mac[4]; + + uint8_t k_nas_enc[32]; + uint8_t k_nas_int[32]; + + srslte::security_generate_k_nas( ue_ctx->k_asme, + srslte::CIPHERING_ALGORITHM_ID_EEA0, + srslte::INTEGRITY_ALGORITHM_ID_128_EIA1, + k_nas_enc, + k_nas_int + ); + + srslte::security_128_eia1 (&k_nas_int[16], + count, + 0, + SECURITY_DIRECTION_DOWNLINK, + &nas_buffer->msg[5], + nas_buffer->N_bytes - 5, + mac + ); + + memcpy(&nas_buffer->msg[1],mac,4); //Copy NAS PDU to Downlink NAS Trasport message buffer memcpy(dw_nas->NAS_PDU.buffer, nas_buffer->msg, nas_buffer->N_bytes); dw_nas->NAS_PDU.n_octets = nas_buffer->N_bytes; From 468b0f2581e48fbcb88f1729fd08910adc7963a8 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 8 Nov 2017 14:10:25 +0000 Subject: [PATCH 058/172] Fixed some issues with the MME and HSS logging. --- lib/src/common/logger_file.cc | 2 +- srsepc/hdr/hss/hss.h | 10 +++------ srsepc/hdr/mme/mme.h | 8 ++----- srsepc/hdr/mme/s1ap.h | 5 +++-- srsepc/src/hss/hss.cc | 18 ++++++---------- srsepc/src/main.cc | 23 +++++++++++++++----- srsepc/src/mme/mme.cc | 40 ++++++++++++++--------------------- srsepc/src/mme/s1ap.cc | 7 +++--- 8 files changed, 54 insertions(+), 59 deletions(-) diff --git a/lib/src/common/logger_file.cc b/lib/src/common/logger_file.cc index 94e5e8405..c1c31523e 100644 --- a/lib/src/common/logger_file.cc +++ b/lib/src/common/logger_file.cc @@ -40,7 +40,7 @@ logger_file::logger_file() logger_file::~logger_file() { not_done = false; - log(new std::string("Closing log")); + log(new std::string("Closing log\n")); if(inited) { wait_thread_finish(); flush(); diff --git a/srsepc/hdr/hss/hss.h b/srsepc/hdr/hss/hss.h index df19aed4e..f8a23809d 100644 --- a/srsepc/hdr/hss/hss.h +++ b/srsepc/hdr/hss/hss.h @@ -53,7 +53,7 @@ class hss public: static hss* get_instance(void); static void cleanup(void); - int init(hss_args_t *hss_args, srslte::logger* logger); + int init(hss_args_t *hss_args, srslte::log_filter* hss_log); void get_sqn(uint8_t sqn[6]); void gen_rand(uint8_t rand_[16]); @@ -66,15 +66,11 @@ private: virtual ~hss(); static hss *m_instance; - uint64_t m_sqn; //48 bits + uint64_t m_sqn; //48 bits srslte::byte_buffer_pool *m_pool; /*Logs*/ - srslte::logger_stdout m_logger_stdout; - srslte::logger_file m_logger_file; - srslte::logger *m_logger; - - srslte::log_filter m_hss_log; + srslte::log_filter *m_hss_log; }; diff --git a/srsepc/hdr/mme/mme.h b/srsepc/hdr/mme/mme.h index 74c74afed..2fec2a23a 100644 --- a/srsepc/hdr/mme/mme.h +++ b/srsepc/hdr/mme/mme.h @@ -66,7 +66,7 @@ class mme: public: static mme* get_instance(void); static void cleanup(void); - int init(mme_args_t* args, srslte::logger *logger); + int init(mme_args_t* args, srslte::log_filter *s1ap_log); void stop(); int get_s1_mme(); void run_thread(); @@ -82,11 +82,7 @@ private: srslte::byte_buffer_pool *m_pool; /*Logs*/ - //srslte::logger_stdout m_logger_stdout; - //srslte::logger_file m_logger_file; - srslte::logger *m_logger; - - srslte::log_filter m_s1ap_log; + srslte::log_filter *m_s1ap_log; }; diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 2887938da..454c31b4d 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -53,7 +53,7 @@ public: s1ap(); virtual ~s1ap(); int enb_listen(); - int init(s1ap_args_t s1ap_args, srslte::log *s1ap_log); + int init(s1ap_args_t s1ap_args, srslte::log_filter *s1ap_log); void stop(); int get_s1_mme(); @@ -79,7 +79,8 @@ private: s1ap_args_t m_s1ap_args; uint32_t m_plmn; srslte::byte_buffer_pool *m_pool; - srslte::log *m_s1ap_log; + srslte::logger *m_logger; + srslte::log_filter *m_s1ap_log; hss *m_hss; int m_s1mme; diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index 4a21f2614..28d70ca69 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -71,18 +71,14 @@ hss::cleanup(void) } int -hss::init(hss_args_t *hss_args, srslte::logger *logger) +hss::init(hss_args_t *hss_args, srslte::log_filter *hss_log) { /*Init loggers*/ - m_logger=logger; - m_hss_log.init("HSS", m_logger); - m_hss_log.set_level(srslte::LOG_LEVEL_DEBUG); - m_hss_log.set_hex_limit(32); - srand(time(NULL)); - m_hss_log.info("Initialized HSS\n"); - m_hss_log.console("Initialized HSS\n"); + m_hss_log = hss_log; + m_hss_log->info("HSS Initialized\n"); + m_hss_log->console("HSS Initialized\n"); return 0; } @@ -169,7 +165,7 @@ hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn } std::cout<console("AUTN: %s", autn_str.c_str()); return true; } @@ -183,11 +179,11 @@ hss::get_k_amf_op(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op ) if(imsi != 1010123456789) { - m_hss_log.console("Usernot found. IMSI: %015lu\n",imsi); + m_hss_log->console("User not found. IMSI: %015lu\n",imsi); return false; } - m_hss_log.console("Found User %015lu\n",imsi); + m_hss_log->console("Found User %015lu\n",imsi); memcpy(k,k_tmp,16); memcpy(amf,amf_tmp,2); memcpy(op,op_tmp,16); diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index d75bc14d2..bcf9e70c6 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -159,7 +159,7 @@ main (int argc,char * argv[] ) /*Init logger*/ - args.log_args.filename = std::string("/tmp/epc.log"); //FIXME + args.log_args.filename = std::string("/tmp/epc.log"); if (!args.log_args.filename.compare("stdout")) { logger = &logger_stdout; } else { @@ -168,17 +168,29 @@ main (int argc,char * argv[] ) logger = &logger_file; } + srslte::log_filter s1ap_log; + s1ap_log.init("S1AP",logger); + s1ap_log.set_level(srslte::LOG_LEVEL_DEBUG); + s1ap_log.set_hex_limit(32); + + srslte::log_filter hss_log; + hss_log.init("HSS ",logger); + hss_log.set_level(srslte::LOG_LEVEL_DEBUG); + hss_log.set_hex_limit(32); + mme *mme = mme::get_instance(); - if (mme->init(&args.mme_args, logger)) { + if (mme->init(&args.mme_args, &s1ap_log)) { cout << "Error initializing MME" << endl; exit(1); } + hss *hss = hss::get_instance(); - if (hss->init(&args.hss_args,logger)) { + if (hss->init(&args.hss_args,&hss_log)) { cout << "Error initializing HSS" << endl; exit(1); } - + + mme->start(); while(running) { @@ -187,7 +199,8 @@ main (int argc,char * argv[] ) mme->stop(); mme->cleanup(); - + + cout << "--- exiting ---" << endl; return 0; } diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index 9cc19030d..bc9e7ea39 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -70,27 +70,19 @@ mme::cleanup(void) } int -mme::init(mme_args_t* args, srslte::logger *logger) +mme::init(mme_args_t* args, srslte::log_filter *s1ap_log) { - /*Init loggers*/ - /* - if (!args->log_args.filename.compare("stdout")) { - m_logger = &m_logger_stdout; - } else { - m_logger_file.init(args->log_args.filename); - m_logger_file.log("\n--- Software Radio Systems MME log ---\n\n"); - m_logger = &m_logger_file; - } - */ - m_s1ap_log.init("S1AP", m_logger); - m_s1ap_log.set_level(srslte::LOG_LEVEL_DEBUG); - m_s1ap_log.set_hex_limit(32); - if(m_s1ap.init(args->s1ap_args, &m_s1ap_log)){ - m_s1ap_log.error("Error initializing MME S1APP\n"); + + /*Init S1AP*/ + if(m_s1ap.init(args->s1ap_args, s1ap_log)){ + m_s1ap_log->error("Error initializing MME S1APP\n"); exit(-1); } - m_s1ap_log.info("Initialized S1-MME\n"); - m_s1ap_log.console("Initialized S1-MME\n"); + + /*Init logger*/ + m_s1ap_log = s1ap_log; + m_s1ap_log->info("MME Initialized\n"); + m_s1ap_log->console("MME Initialized\n"); return 0; } @@ -127,30 +119,30 @@ mme::run_thread() int s1mme = m_s1ap.get_s1_mme(); while(m_running) { - m_s1ap_log.debug("Waiting for SCTP Msg\n"); + m_s1ap_log->debug("Waiting for SCTP Msg\n"); pdu->reset(); rd_sz = sctp_recvmsg(s1mme, pdu->msg, sz,(struct sockaddr*) &enb_addr, &fromlen, &sri, &msg_flags); if (rd_sz == -1 && errno != EAGAIN){ - m_s1ap_log.error("Error reading from SCTP socket: %s", strerror(errno)); + m_s1ap_log->error("Error reading from SCTP socket: %s", strerror(errno)); } else if (rd_sz == -1 && errno == EAGAIN){ - m_s1ap_log.debug("Socket timeout reached"); + m_s1ap_log->debug("Socket timeout reached"); } else{ if(msg_flags & MSG_NOTIFICATION) { //Received notification - m_s1ap_log.console("SCTP Notification %d\n", ((union sctp_notification*)pdu->msg)->sn_header.sn_type); + m_s1ap_log->console("SCTP Notification %d\n", ((union sctp_notification*)pdu->msg)->sn_header.sn_type); if (((union sctp_notification*)pdu->msg)->sn_header.sn_type == SCTP_SHUTDOWN_EVENT) { - m_s1ap_log.console("SCTP Association Gracefully Shutdown\n");//TODO + m_s1ap_log->console("SCTP Association Gracefully Shutdown\n");//TODO } } else { //Received data pdu->N_bytes = rd_sz; - m_s1ap_log.info("Received S1AP msg. Size: %d\n", pdu->N_bytes); + m_s1ap_log->info("Received S1AP msg. Size: %d\n", pdu->N_bytes); m_s1ap.handle_s1ap_rx_pdu(pdu,&sri); } } diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 89b0a24f0..b2da4fdaa 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -42,9 +42,9 @@ s1ap::~s1ap() } int -s1ap::init(s1ap_args_t s1ap_args, srslte::log *s1ap_log) +s1ap::init(s1ap_args_t s1ap_args, srslte::log_filter *s1ap_log) { - + m_s1ap_args = s1ap_args; srslte::s1ap_mccmnc_to_plmn(s1ap_args.mcc, s1ap_args.mnc, &m_plmn); @@ -56,6 +56,7 @@ s1ap::init(s1ap_args_t s1ap_args, srslte::log *s1ap_log) m_s1mme = enb_listen(); + m_s1ap_log->info("S1AP Initialized\n"); return 0; } @@ -89,7 +90,7 @@ s1ap::enb_listen() struct sockaddr_in s1mme_addr; struct sctp_event_subscribe evnts; - m_s1ap_log->console("Initializing S1-MME\n"); + m_s1ap_log->info("S1-MME Initializing\n"); sock_fd = socket (AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); if (sock_fd == -1){ m_s1ap_log->console("Could not create SCTP socket\n"); From 82b661541faeac4caa19f3b459ee0fb19de270b4 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 8 Nov 2017 14:23:17 +0000 Subject: [PATCH 059/172] removed some white space --- srsepc/src/main.cc | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index bcf9e70c6..366ffaf5f 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -190,16 +190,13 @@ main (int argc,char * argv[] ) exit(1); } - - mme->start(); - + mme->start(); while(running) { sleep(1); } mme->stop(); - mme->cleanup(); - + mme->cleanup(); cout << "--- exiting ---" << endl; return 0; From a77308b4b8c2ad1c0db0fa99dc049373dc9d000b Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 8 Nov 2017 18:00:44 +0000 Subject: [PATCH 060/172] Starting to add a function to parse security command complete. --- srsepc/hdr/mme/s1ap.h | 2 + srsepc/src/mme/s1ap.cc | 85 ++++++++++++++++++++++++++++-------------- 2 files changed, 60 insertions(+), 27 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 454c31b4d..33a9a57e3 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -72,6 +72,8 @@ public: bool handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, struct sctp_sndrcvinfo *enb_sri); + bool handle_nas_authentication_response(srslte::byte_buffer_t *nas_buffer, srslte::byte_buffer_t *reply_buffer, ue_ctx_t *ue_ctx); + void print_enb_ctx_info(const enb_ctx_t &enb_ctx); private: diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index b2da4fdaa..cbd332267 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -142,19 +142,19 @@ s1ap::handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb switch(rx_pdu.choice_type) { case LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE: - m_s1ap_log->console("Received initiating PDU\n"); + m_s1ap_log->info("Received initiating PDU\n"); return handle_initiating_message(&rx_pdu.choice.initiatingMessage, enb_sri); break; case LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME: - m_s1ap_log->console("Received Succeseful Outcome PDU\n"); + m_s1ap_log->info("Received Succeseful Outcome PDU\n"); return true;//handle_successfuloutcome(&rx_pdu.choice.successfulOutcome); break; case LIBLTE_S1AP_S1AP_PDU_CHOICE_UNSUCCESSFULOUTCOME: - m_s1ap_log->console("Received Unsucceseful Outcome PDU\n"); + m_s1ap_log->info("Received Unsucceseful Outcome PDU\n"); return true;//handle_unsuccessfuloutcome(&rx_pdu.choice.unsuccessfulOutcome); break; default: - m_s1ap_log->console("Unhandled PDU type %d\n", rx_pdu.choice_type); + m_s1ap_log->error("Unhandled PDU type %d\n", rx_pdu.choice_type); return false; } @@ -173,7 +173,7 @@ s1ap::handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, stru m_s1ap_log->info("Received Initial UE Message.\n"); return handle_initial_ue_message(&msg->choice.InitialUEMessage, enb_sri); case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UPLINKNASTRANSPORT: - m_s1ap_log->info("Received Initial UE Message.\n"); + m_s1ap_log->info("Received Uplink NAS Transport Message.\n"); return handle_uplink_nas_transport(&msg->choice.UplinkNASTransport, enb_sri); default: m_s1ap_log->error("Unhandled intiating message: %s\n", liblte_s1ap_initiatingmessage_choice_text[msg->choice_type]); @@ -202,8 +202,8 @@ s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, st //Check matching PLMNs if(enb_ctx.plmn!=m_plmn){ - m_s1ap_log->console("S1 Setup Failure - Unkown PLMN\n"); - m_s1ap_log->info("S1 Setup Failure - Unkown PLMN\n"); + m_s1ap_log->console("Sending S1 Setup Failure - Unkown PLMN\n"); + m_s1ap_log->info("Sending S1 Setup Failure - Unkown PLMN\n"); m_s1ap_mngmt_proc.pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_UNKNOWN_PLMN,&reply_msg); } else{ @@ -223,8 +223,8 @@ s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, st //m_active_enbs.insert(std::pair(enb_ctx.enb_id,enb_ctx)); m_s1ap_mngmt_proc.pack_s1_setup_response(m_s1ap_args, &reply_msg); - m_s1ap_log->console("S1 Setup Response\n"); - m_s1ap_log->info("S1 Setup Response\n"); + m_s1ap_log->console("Sending S1 Setup Response\n"); + m_s1ap_log->info("Sending S1 Setup Response\n"); } //Send Reply to eNB @@ -323,8 +323,7 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT uint32_t mme_ue_s1ap_id = ul_xport->MME_UE_S1AP_ID.MME_UE_S1AP_ID; ue_ctx_t *ue_ctx; - LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT auth_resp; - srslte::byte_buffer_t *reply_msg; + srslte::byte_buffer_t *reply_msg = m_pool->allocate(); m_s1ap_log->console("Received Uplink NAS Transport message. MME-UE S1AP Id: %d\n",mme_ue_s1ap_id); m_s1ap_log->info("Received Uplink NAS Transport message. MME-UE S1AP Id: %d\n",mme_ue_s1ap_id); @@ -339,10 +338,54 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT } m_s1ap_log->console("Found UE. MME-UE S1AP id: %lu",mme_ue_s1ap_id); - //Get NAS authentication response - if(!m_s1ap_nas_transport.unpack_authentication_response(ul_xport, &auth_resp)) + //Get NAS message type + uint8_t pd, msg_type; + srslte::byte_buffer_t *nas_msg = m_pool->allocate(); + + memcpy(nas_msg->msg, &ul_xport->NAS_PDU.buffer, ul_xport->NAS_PDU.n_octets); + nas_msg->N_bytes = ul_xport->NAS_PDU.n_octets; + liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &pd, &msg_type); + + switch (msg_type) { + case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE: + handle_nas_authentication_response(nas_msg, reply_msg, ue_ctx); + m_s1ap_log->info("UL NAS: Received Authentication Response\n"); + break; + case LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMPLETE: + m_s1ap_log->info("UL NAS: Received Security Mode Complete\n"); + break; + default: + m_s1ap_log->info("Unhandled NAS message"); + return false; //FIXME cleanup (deallocate needs to be called) + } + + + //Send Reply to eNB + ssize_t n_sent = sctp_send(m_s1mme,reply_msg->msg, reply_msg->N_bytes, enb_sri, 0); + if(n_sent == -1) { - m_s1ap_log->warning("Error unpacking authentication response\n"); + m_s1ap_log->console("Failed to send NAS Attach Request"); + return false; + } + m_s1ap_log->console("Sent Security Mode Command\n"); + + m_pool->deallocate(nas_msg); + m_pool->deallocate(reply_msg); + + return true; +} + +bool +s1ap::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx) +{ + + LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT auth_resp; + bool ue_valid=true; + + //Get NAS authentication response + LIBLTE_ERROR_ENUM err = liblte_mme_unpack_authentication_response_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &auth_resp); + if(err != LIBLTE_SUCCESS){ + m_s1ap_log->error("Error unpacking NAS authentication response. Error: %s\n", liblte_error_text[err]); return false; } @@ -370,23 +413,11 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT } m_s1ap_log->console("UE Authentication Accepted. IMSI: %lu\n", ue_ctx->imsi); - //Send Security Mode Command - reply_msg = m_pool->allocate(); m_s1ap_nas_transport.pack_security_mode_command(reply_msg, ue_ctx); - - //Send Reply to eNB - ssize_t n_sent = sctp_send(m_s1mme,reply_msg->msg, reply_msg->N_bytes, enb_sri, 0); - if(n_sent == -1) - { - m_s1ap_log->console("Failed to send NAS Attach Request"); - return false; - } - m_s1ap_log->console("Sent Security Mode Command\n"); - m_pool->deallocate(reply_msg); - return true; } + void s1ap::print_enb_ctx_info(const enb_ctx_t &enb_ctx) { From c0490693465a9c9e45fef8f8a5600dc2b5c0b813 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 8 Nov 2017 18:44:27 +0000 Subject: [PATCH 061/172] Added a function to handle the security mode complete. --- srsepc/hdr/mme/s1ap.h | 3 +++ srsepc/src/mme/s1ap.cc | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 33a9a57e3..48d2403fe 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -74,6 +74,9 @@ public: bool handle_nas_authentication_response(srslte::byte_buffer_t *nas_buffer, srslte::byte_buffer_t *reply_buffer, ue_ctx_t *ue_ctx); + bool handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx); + + void print_enb_ctx_info(const enb_ctx_t &enb_ctx); private: diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index cbd332267..d1e3c3f0b 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -353,6 +353,8 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT break; case LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMPLETE: m_s1ap_log->info("UL NAS: Received Security Mode Complete\n"); + handle_nas_security_mode_complete(nas_msg, reply_msg, ue_ctx); + return true; //no need for reply. FIXME this should be better structured... break; default: m_s1ap_log->info("Unhandled NAS message"); @@ -418,6 +420,36 @@ s1ap::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, srslte: return true; } +bool +s1ap::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx) +{ + /* + typedef struct{ + LIBLTE_MME_MOBILE_ID_STRUCT imeisv; + bool imeisv_present; + }LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT; + */ + LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT sm_comp; + + //Get NAS authentication response + LIBLTE_ERROR_ENUM err = liblte_mme_unpack_security_mode_complete_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &sm_comp); + if(err != LIBLTE_SUCCESS){ + m_s1ap_log->error("Error unpacking NAS authentication response. Error: %s\n", liblte_error_text[err]); + return false; + } + + //TODO Check integrity + + //TODO Handle imeisv + if(sm_comp.imeisv_present) + { + m_s1ap_log->warning("IMEI-SV present but not handled"); + } + + m_s1ap_log->console("Received Security Mode Command Complete. IMSI: %lu\n", ue_ctx->imsi); + return true; +} + void s1ap::print_enb_ctx_info(const enb_ctx_t &enb_ctx) { From eba3837ab4d45204b8c2dc5c98c8f67a9c82384a Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 9 Nov 2017 13:09:30 +0000 Subject: [PATCH 062/172] Changing the logging a bit. --- srsepc/src/hss/hss.cc | 27 +++++---------------------- srsepc/src/mme/s1ap.cc | 17 ++++++++++------- srsepc/src/mme/s1ap_nas_transport.cc | 3 ++- 3 files changed, 17 insertions(+), 30 deletions(-) diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index 28d70ca69..98058b77b 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -143,29 +143,10 @@ hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn autn[8+i]=mac[i]; } + m_hss_log->debug_hex(sqn, 6, "User SQN : "); + m_hss_log->debug_hex(autn, 8, "User AUTN: "); + m_hss_log->debug_hex(xres, 8, "User XRES: "); - - //std::stringstream ss; - std::cout<<"SQN: "; - for(int i=0;i<6;i++) - { - std::cout << std::hex <<(uint16_t)sqn[i]; - } - std::cout<console("AUTN: %s", autn_str.c_str()); return true; } @@ -179,10 +160,12 @@ hss::get_k_amf_op(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op ) if(imsi != 1010123456789) { + m_hss_log->info("User not found. IMSI: %015lu\n",imsi); m_hss_log->console("User not found. IMSI: %015lu\n",imsi); return false; } + m_hss_log->info("Found User %015lu\n",imsi); m_hss_log->console("Found User %015lu\n",imsi); memcpy(k,k_tmp,16); memcpy(amf,amf_tmp,2); diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index d1e3c3f0b..e81c609a5 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -305,10 +305,10 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini ssize_t n_sent = sctp_send(m_s1mme,reply_msg->msg, reply_msg->N_bytes, enb_sri, 0); if(n_sent == -1) { - m_s1ap_log->console("Failed to send NAS Attach Request"); + m_s1ap_log->error("Failed to send NAS Attach Request"); return false; } - m_s1ap_log->console("Sent NAS Athentication Request\n"); + m_s1ap_log->info("DL NAS: Sent Athentication Request\n"); m_pool->deallocate(reply_msg); //TODO Start T3460 Timer! return true; @@ -333,10 +333,10 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT if(it == m_active_ues.end()) { //TODO UE not registered, send error message. - m_s1ap_log->console("Could not find UE. MME-UE S1AP id: %lu\n",mme_ue_s1ap_id); + m_s1ap_log->warning("Could not find UE. MME-UE S1AP id: %lu\n",mme_ue_s1ap_id); return false; } - m_s1ap_log->console("Found UE. MME-UE S1AP id: %lu",mme_ue_s1ap_id); + m_s1ap_log->debug("Found UE. MME-UE S1AP id: %lu",mme_ue_s1ap_id); //Get NAS message type uint8_t pd, msg_type; @@ -366,11 +366,11 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT ssize_t n_sent = sctp_send(m_s1mme,reply_msg->msg, reply_msg->N_bytes, enb_sri, 0); if(n_sent == -1) { - m_s1ap_log->console("Failed to send NAS Attach Request"); + m_s1ap_log->error("Failed to send NAS Attach Request"); return false; } - m_s1ap_log->console("Sent Security Mode Command\n"); - + m_s1ap_log->info("DL NAS: Sent Security Mode Command\n"); + m_s1ap_log->console("DL NAS: Sent Security Mode Command\n"); m_pool->deallocate(nas_msg); m_pool->deallocate(reply_msg); @@ -414,6 +414,7 @@ s1ap::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, srslte: return false; } m_s1ap_log->console("UE Authentication Accepted. IMSI: %lu\n", ue_ctx->imsi); + m_s1ap_log->info("UE Authentication Accepted. IMSI: %lu\n", ue_ctx->imsi); //Send Security Mode Command m_s1ap_nas_transport.pack_security_mode_command(reply_msg, ue_ctx); @@ -446,7 +447,9 @@ s1ap::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, srslte:: m_s1ap_log->warning("IMEI-SV present but not handled"); } + m_s1ap_log->info("Received Security Mode Command Complete. IMSI: %lu\n", ue_ctx->imsi); m_s1ap_log->console("Received Security Mode Command Complete. IMSI: %lu\n", ue_ctx->imsi); + return true; } diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index d2212ad2f..f3b20f022 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -122,7 +122,6 @@ s1ap_nas_transport::pack_authentication_request(srslte::byte_buffer_t *reply_msg dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = enb_ue_s1ap_id; dw_nas->HandoverRestrictionList_present=false; dw_nas->SubscriberProfileIDforRFP_present=false; - m_s1ap_log->console("Dw NAS id %d\n", enb_ue_s1ap_id); //Pack NAS PDU LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT auth_req; @@ -134,6 +133,7 @@ s1ap_nas_transport::pack_authentication_request(srslte::byte_buffer_t *reply_msg LIBLTE_ERROR_ENUM err = liblte_mme_pack_authentication_request_msg(&auth_req, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); if(err != LIBLTE_SUCCESS) { + m_s1ap_log->error("Error packing Athentication Request\n"); m_s1ap_log->console("Error packing Athentication Request\n"); return false; } @@ -146,6 +146,7 @@ s1ap_nas_transport::pack_authentication_request(srslte::byte_buffer_t *reply_msg err = liblte_s1ap_pack_s1ap_pdu(&tx_pdu, (LIBLTE_BYTE_MSG_STRUCT *) reply_msg); if(err != LIBLTE_SUCCESS) { + m_s1ap_log->error("Error packing Athentication Request\n"); m_s1ap_log->console("Error packing Athentication Request\n"); return false; } From 87b775d94bdc75f732ec300ffef80752a26547b0 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 9 Nov 2017 17:43:40 +0000 Subject: [PATCH 063/172] Added functionallity to delete eNB context when SCTP session is terminated. --- srsepc/hdr/mme/s1ap.h | 5 ++++- srsepc/src/mme/mme.cc | 9 ++++++--- srsepc/src/mme/s1ap.cc | 30 +++++++++++++++++++++++++++--- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 48d2403fe..4b895c2f6 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -57,7 +57,9 @@ public: void stop(); int get_s1_mme(); - + + void delete_enb_ctx(int32_t assoc_id); + bool handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb_sri); bool handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri); @@ -90,6 +92,7 @@ private: hss *m_hss; int m_s1mme; std::map m_active_enbs; + std::map m_sctp_to_enb_id; std::map m_active_ues; uint32_t m_next_mme_ue_s1ap_id; diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index bc9e7ea39..a8629f2fc 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -132,10 +132,13 @@ mme::run_thread() if(msg_flags & MSG_NOTIFICATION) { //Received notification - m_s1ap_log->console("SCTP Notification %d\n", ((union sctp_notification*)pdu->msg)->sn_header.sn_type); - if (((union sctp_notification*)pdu->msg)->sn_header.sn_type == SCTP_SHUTDOWN_EVENT) + union sctp_notification *notification = (union sctp_notification*)pdu->msg; + m_s1ap_log->debug("SCTP Notification %d\n", notification->sn_header.sn_type); + if (notification->sn_header.sn_type == SCTP_SHUTDOWN_EVENT) { - m_s1ap_log->console("SCTP Association Gracefully Shutdown\n");//TODO + m_s1ap_log->info("SCTP Association Shutdown. Association: %d\n",sri.sinfo_assoc_id); + m_s1ap_log->console("SCTP Association Shutdown. Association: %d\n",sri.sinfo_assoc_id); + m_s1ap.delete_enb_ctx(sri.sinfo_assoc_id); } } else diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index e81c609a5..a4c1b6d5f 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -69,13 +69,33 @@ s1ap::stop() std::map::iterator it = m_active_enbs.begin(); while(it!=m_active_enbs.end()) { - print_enb_ctx_info(*it->second); + m_s1ap_log->info("Deleting eNB context. eNB Id: 0x%x\n", it->second->enb_id); + m_s1ap_log->console("Deleting eNB context. eNB Id: 0x%x\n", it->second->enb_id); delete it->second; m_active_enbs.erase(it++); } return; } +void +s1ap::delete_enb_ctx(int32_t assoc_id) +{ + std::map::iterator it_assoc = m_sctp_to_enb_id.find(assoc_id); + uint16_t enb_id = it_assoc->second; + std::map::iterator it_ctx = m_active_enbs.find(enb_id); + if(it_ctx == m_active_enbs.end() || it_assoc == m_sctp_to_enb_id.end()) + { + m_s1ap_log->error("Could not find eNB to delete. Association: %d\n",assoc_id); + return; + } + delete it_ctx->second; + m_active_enbs.erase(it_ctx); + m_sctp_to_enb_id.erase(it_assoc); + m_s1ap_log->info("Deleting eNB context. eNB Id: 0x%x\n", enb_id); + m_s1ap_log->console("Deleting eNB context. eNB Id: 0x%x\n", enb_id); + return; +} + int s1ap::get_s1_mme() { @@ -130,6 +150,9 @@ s1ap::enb_listen() return sock_fd; } + + + bool s1ap::handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb_sri) { @@ -198,6 +221,7 @@ s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, st } //Log S1 Setup Request Info + m_s1ap_log->console("Received S1 Setup Request. Association: %d\n",enb_sri->sinfo_assoc_id); print_enb_ctx_info(enb_ctx); //Check matching PLMNs @@ -216,12 +240,12 @@ s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, st else { //new eNB - enb_ctx_t *enb_ptr = new enb_ctx_t;//TODO use buffer pool here? + enb_ctx_t *enb_ptr = new enb_ctx_t; memcpy(enb_ptr,&enb_ctx,sizeof(enb_ctx)); m_active_enbs.insert(std::pair(enb_ptr->enb_id,enb_ptr)); + m_sctp_to_enb_id.insert(std::pair(enb_sri->sinfo_assoc_id, enb_ptr->enb_id)); } - //m_active_enbs.insert(std::pair(enb_ctx.enb_id,enb_ctx)); m_s1ap_mngmt_proc.pack_s1_setup_response(m_s1ap_args, &reply_msg); m_s1ap_log->console("Sending S1 Setup Response\n"); m_s1ap_log->info("Sending S1 Setup Response\n"); From 1f52d1741ced2a6e9353415ad0eaf958ab48195d Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 10 Nov 2017 15:21:56 +0000 Subject: [PATCH 064/172] Added the mechanisms to remove UE's context when the eNB is terminated. --- srsepc/hdr/mme/s1ap.h | 21 ++++++++---------- srsepc/src/mme/s1ap.cc | 48 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 50 insertions(+), 19 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 4b895c2f6..8c659ac18 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -38,6 +38,7 @@ #include #include #include +#include #include "mme/s1ap_common.h" #include "mme/s1ap_mngmt_proc.h" #include "mme/s1ap_nas_transport.h" @@ -59,23 +60,19 @@ public: int get_s1_mme(); void delete_enb_ctx(int32_t assoc_id); + void delete_ues_in_enb(uint16_t enb_id); + bool handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb_sri); - bool handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri); bool handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri); - bool send_s1_setup_failure(struct sctp_sndrcvinfo *enb_sri); - bool send_s1_setup_response(struct sctp_sndrcvinfo *enb_sri); - bool handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, struct sctp_sndrcvinfo *enb_sri); - + bool handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, struct sctp_sndrcvinfo *enb_sri); bool handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, struct sctp_sndrcvinfo *enb_sri); - bool handle_nas_authentication_response(srslte::byte_buffer_t *nas_buffer, srslte::byte_buffer_t *reply_buffer, ue_ctx_t *ue_ctx); - bool handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx); @@ -91,11 +88,11 @@ private: hss *m_hss; int m_s1mme; - std::map m_active_enbs; - std::map m_sctp_to_enb_id; - std::map m_active_ues; - - uint32_t m_next_mme_ue_s1ap_id; + std::map m_active_enbs; + std::map m_sctp_to_enb_id; + std::map m_active_ues; + std::map > m_enb_id_to_ue_ids; + uint32_t m_next_mme_ue_s1ap_id; s1ap_mngmt_proc m_s1ap_mngmt_proc; s1ap_nas_transport m_s1ap_nas_transport; diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index a4c1b6d5f..3ed3a11ca 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -71,6 +71,7 @@ s1ap::stop() { m_s1ap_log->info("Deleting eNB context. eNB Id: 0x%x\n", it->second->enb_id); m_s1ap_log->console("Deleting eNB context. eNB Id: 0x%x\n", it->second->enb_id); + delete_ues_in_enb(it->second->enb_id); delete it->second; m_active_enbs.erase(it++); } @@ -79,23 +80,49 @@ s1ap::stop() void s1ap::delete_enb_ctx(int32_t assoc_id) -{ +{ std::map::iterator it_assoc = m_sctp_to_enb_id.find(assoc_id); uint16_t enb_id = it_assoc->second; + std::map::iterator it_ctx = m_active_enbs.find(enb_id); if(it_ctx == m_active_enbs.end() || it_assoc == m_sctp_to_enb_id.end()) { m_s1ap_log->error("Could not find eNB to delete. Association: %d\n",assoc_id); return; } + + m_s1ap_log->info("Deleting eNB context. eNB Id: 0x%x\n", enb_id); + m_s1ap_log->console("Deleting eNB context. eNB Id: 0x%x\n", enb_id); + + //Delete connected UEs ctx + delete_ues_in_enb(enb_id); + + //Delete eNB delete it_ctx->second; m_active_enbs.erase(it_ctx); m_sctp_to_enb_id.erase(it_assoc); - m_s1ap_log->info("Deleting eNB context. eNB Id: 0x%x\n", enb_id); - m_s1ap_log->console("Deleting eNB context. eNB Id: 0x%x\n", enb_id); - return; + return; } +void +s1ap::delete_ues_in_enb(uint16_t enb_id) +{ + //delete UEs ctx + std::map >::iterator ues_in_enb = m_enb_id_to_ue_ids.find(enb_id); + std::set::iterator ue_id = ues_in_enb->second.begin(); + while(ue_id != ues_in_enb->second.end() ) + { + std::map::iterator ue_ctx = m_active_ues.find(*ue_id); + m_s1ap_log->info("Deleting UE context. UE IMSI: %lu\n", ue_ctx->second->imsi); + m_s1ap_log->console("Deleting UE context. UE IMSI: %lu\n", ue_ctx->second->imsi); + delete ue_ctx->second; //delete UE context + m_active_ues.erase(ue_ctx); //remove from general MME map + ues_in_enb->second.erase(ue_id++); //erase from the eNB's UE set + } + +} + + int s1ap::get_s1_mme() { @@ -170,11 +197,11 @@ s1ap::handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb break; case LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME: m_s1ap_log->info("Received Succeseful Outcome PDU\n"); - return true;//handle_successfuloutcome(&rx_pdu.choice.successfulOutcome); + return true;//TODO handle_successfuloutcome(&rx_pdu.choice.successfulOutcome); break; case LIBLTE_S1AP_S1AP_PDU_CHOICE_UNSUCCESSFULOUTCOME: m_s1ap_log->info("Received Unsucceseful Outcome PDU\n"); - return true;//handle_unsuccessfuloutcome(&rx_pdu.choice.unsuccessfulOutcome); + return true;//TODO handle_unsuccessfuloutcome(&rx_pdu.choice.unsuccessfulOutcome); break; default: m_s1ap_log->error("Unhandled PDU type %d\n", rx_pdu.choice_type); @@ -240,10 +267,12 @@ s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, st else { //new eNB + std::set ue_set; enb_ctx_t *enb_ptr = new enb_ctx_t; memcpy(enb_ptr,&enb_ctx,sizeof(enb_ctx)); m_active_enbs.insert(std::pair(enb_ptr->enb_id,enb_ptr)); m_sctp_to_enb_id.insert(std::pair(enb_sri->sinfo_assoc_id, enb_ptr->enb_id)); + m_enb_id_to_ue_ids.insert(std::pair >(enb_ptr->enb_id,ue_set)); } m_s1ap_mngmt_proc.pack_s1_setup_response(m_s1ap_args, &reply_msg); @@ -317,10 +346,15 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini ue_ctx.imsi = imsi; ue_ctx.mme_ue_s1ap_id = m_next_mme_ue_s1ap_id++; - ue_ctx_t *ue_ptr = new ue_ctx_t;//TODO use buffer pool here? + ue_ctx_t *ue_ptr = new ue_ctx_t; memcpy(ue_ptr,&ue_ctx,sizeof(ue_ctx)); m_active_ues.insert(std::pair(ue_ptr->mme_ue_s1ap_id,ue_ptr)); + std::map::iterator it_enb = m_sctp_to_enb_id.find(enb_sri->sinfo_assoc_id); + uint16_t enb_id = it_enb->second; + std::map >::iterator it_ue_id = m_enb_id_to_ue_ids.find(enb_id); + it_ue_id->second.insert(ue_ptr->mme_ue_s1ap_id); + //Pack NAS Authentication Request in Downlink NAS Transport msg srslte::byte_buffer_t *reply_msg = m_pool->allocate(); m_s1ap_nas_transport.pack_authentication_request(reply_msg, ue_ctx.enb_ue_s1ap_id, ue_ctx.mme_ue_s1ap_id, autn, rand); From 150a747181904b3801d5e54f6d247a864785f31e Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 10 Nov 2017 18:18:32 +0000 Subject: [PATCH 065/172] Handling UE Context release to cleanup UE context. --- srsepc/hdr/mme/s1ap.h | 2 ++ srsepc/src/mme/s1ap.cc | 48 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 8c659ac18..23a01dac9 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -72,6 +72,8 @@ public: bool handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, struct sctp_sndrcvinfo *enb_sri); bool handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, struct sctp_sndrcvinfo *enb_sri); + bool handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri); + bool handle_nas_authentication_response(srslte::byte_buffer_t *nas_buffer, srslte::byte_buffer_t *reply_buffer, ue_ctx_t *ue_ctx); bool handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx); diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 3ed3a11ca..0b5312db7 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -225,6 +225,9 @@ s1ap::handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, stru case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UPLINKNASTRANSPORT: m_s1ap_log->info("Received Uplink NAS Transport Message.\n"); return handle_uplink_nas_transport(&msg->choice.UplinkNASTransport, enb_sri); + case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UECONTEXTRELEASEREQUEST: + m_s1ap_log->info("Received UE Context Release Request Message.\n"); + return handle_ue_context_release_request(&msg->choice.UEContextReleaseRequest, enb_sri); default: m_s1ap_log->error("Unhandled intiating message: %s\n", liblte_s1ap_initiatingmessage_choice_text[msg->choice_type]); } @@ -482,12 +485,6 @@ s1ap::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, srslte: bool s1ap::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx) { - /* - typedef struct{ - LIBLTE_MME_MOBILE_ID_STRUCT imeisv; - bool imeisv_present; - }LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT; - */ LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT sm_comp; //Get NAS authentication response @@ -511,6 +508,45 @@ s1ap::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, srslte:: return true; } +bool +s1ap::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri) +{ + + uint32_t mme_ue_s1ap_id = ue_rel->MME_UE_S1AP_ID.MME_UE_S1AP_ID; + m_s1ap_log->info("Received UE Context Release Request. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); + m_s1ap_log->console("Received UE Context Release Request. MME-UE S1AP Id %d\n", mme_ue_s1ap_id); + + std::map::iterator ue_ctx = m_active_ues.find(mme_ue_s1ap_id); + if(ue_ctx == m_active_ues.end() ) + { + m_s1ap_log->info("UE not found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); + return false; + } + + //Delete UE within eNB UE set + std::map::iterator it = m_sctp_to_enb_id.find(enb_sri->sinfo_assoc_id); + if(it == m_sctp_to_enb_id.end() ) + { + m_s1ap_log->error("Could not find eNB for this request.\n"); + return false; + } + uint16_t enb_id = it->second; + std::map >::iterator ue_set = m_enb_id_to_ue_ids.find(enb_id); + if(ue_set == m_enb_id_to_ue_ids.end()) + { + m_s1ap_log->error("Could not find the eNB's UEs.\n"); + return false; + } + ue_set->second.erase(mme_ue_s1ap_id); + + //Delete UE context + delete ue_ctx->second; + m_active_ues.erase(ue_ctx); + m_s1ap_log->info("Deleted UE Context.\n"); + return true; +} + + void s1ap::print_enb_ctx_info(const enb_ctx_t &enb_ctx) { From f908439ed4ded02743a2ea6e77d7858d8d39b373 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 10 Nov 2017 19:32:32 +0000 Subject: [PATCH 066/172] Added the Authentication reject nas message. --- srsepc/hdr/mme/s1ap_nas_transport.h | 2 ++ srsepc/src/mme/s1ap.cc | 4 ++- srsepc/src/mme/s1ap_nas_transport.cc | 52 +++++++++++++++++++++++++++- 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/srsepc/hdr/mme/s1ap_nas_transport.h b/srsepc/hdr/mme/s1ap_nas_transport.h index 03444cee7..f4e207ce6 100644 --- a/srsepc/hdr/mme/s1ap_nas_transport.h +++ b/srsepc/hdr/mme/s1ap_nas_transport.h @@ -41,6 +41,8 @@ public: void set_log(srslte::log *s1ap_logger); bool unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req, LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req); bool pack_authentication_request(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t next_mme_ue_s1ap_id, uint8_t *autn,uint8_t *rand); + bool pack_authentication_reject(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id); + bool unpack_authentication_response(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT *auth_resp); bool pack_security_mode_command(srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx); diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 0b5312db7..5c9ab9093 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -320,7 +320,8 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini /*Get NAS Attach Request and PDN connectivity request messages*/ if(!m_s1ap_nas_transport.unpack_initial_ue_message(init_ue, &attach_req,&pdn_con_req)) { - //TODO set up error reply + //Could not decode the attach request and the PDN connectivity request. + m_s1ap_log->error("Could not unpack NAS Attach Request and PDN connectivity request.\n"); return false; } @@ -472,6 +473,7 @@ s1ap::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, srslte: m_s1ap_log->console("UE Authentication Rejected. IMSI: %lu\n", ue_ctx->imsi); m_s1ap_log->warning("UE Authentication Rejected. IMSI: %lu\n", ue_ctx->imsi); //TODO send back error reply + m_s1ap_nas_transport.pack_authentication_reject(reply_msg, ue_ctx->enb_ue_s1ap_id, ue_ctx->mme_ue_s1ap_id); return false; } m_s1ap_log->console("UE Authentication Accepted. IMSI: %lu\n", ue_ctx->imsi); diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index f3b20f022..2400edc17 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -118,7 +118,7 @@ s1ap_nas_transport::pack_authentication_request(srslte::byte_buffer_t *reply_msg //Setup Dw NAS structure LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT *dw_nas = &init->choice.DownlinkNASTransport; dw_nas->ext=false; - dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = next_mme_ue_s1ap_id; + dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = next_mme_ue_s1ap_id;//FIXME Change name dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = enb_ue_s1ap_id; dw_nas->HandoverRestrictionList_present=false; dw_nas->SubscriberProfileIDforRFP_present=false; @@ -156,6 +156,56 @@ s1ap_nas_transport::pack_authentication_request(srslte::byte_buffer_t *reply_msg return true; } +bool +s1ap_nas_transport::pack_authentication_reject(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id) +{ + srslte::byte_buffer_t *nas_buffer = m_pool->allocate(); + + //Setup initiating message + LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu; + bzero(&tx_pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); + + tx_pdu.ext = false; + tx_pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE; + + LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *init = &tx_pdu.choice.initiatingMessage; + init->procedureCode = LIBLTE_S1AP_PROC_ID_DOWNLINKNASTRANSPORT; + init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DOWNLINKNASTRANSPORT; + + //Setup Dw NAS structure + LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT *dw_nas = &init->choice.DownlinkNASTransport; + dw_nas->ext=false; + dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = mme_ue_s1ap_id;//FIXME Change name + dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = enb_ue_s1ap_id; + dw_nas->HandoverRestrictionList_present=false; + dw_nas->SubscriberProfileIDforRFP_present=false; + + LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT auth_rej; + LIBLTE_ERROR_ENUM err = liblte_mme_pack_authentication_request_msg(&auth_rej, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + if(err != LIBLTE_SUCCESS) + { + m_s1ap_log->error("Error packing Athentication Request\n"); + m_s1ap_log->console("Error packing Athentication Request\n"); + return false; + } + + //Copy NAS PDU to Downlink NAS Trasport message buffer + memcpy(dw_nas->NAS_PDU.buffer, nas_buffer->msg, nas_buffer->N_bytes); + dw_nas->NAS_PDU.n_octets = nas_buffer->N_bytes; + + //Pack Downlink NAS Transport Message + err = liblte_s1ap_pack_s1ap_pdu(&tx_pdu, (LIBLTE_BYTE_MSG_STRUCT *) reply_msg); + if(err != LIBLTE_SUCCESS) + { + m_s1ap_log->error("Error packing Athentication Reject\n"); + m_s1ap_log->console("Error packing Athentication Reject\n"); + return false; + } + + m_pool->deallocate(nas_buffer); + return true; +} + bool s1ap_nas_transport::unpack_authentication_response(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT *auth_resp ) From d0c0d29f6248705308b748bf6d77ca58e76df832 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 13 Nov 2017 12:35:53 +0000 Subject: [PATCH 067/172] Packing and sending Authentication Reject if XRES != RES --- srsepc/src/mme/s1ap.cc | 20 +++++++++++--------- srsepc/src/mme/s1ap_nas_transport.cc | 12 ++++++------ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 5c9ab9093..3f1a461cf 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -420,7 +420,7 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT break; default: m_s1ap_log->info("Unhandled NAS message"); - return false; //FIXME cleanup (deallocate needs to be called) + return false; //FIXME (nas_msg deallocate needs to be called) } @@ -431,8 +431,8 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT m_s1ap_log->error("Failed to send NAS Attach Request"); return false; } - m_s1ap_log->info("DL NAS: Sent Security Mode Command\n"); - m_s1ap_log->console("DL NAS: Sent Security Mode Command\n"); + m_s1ap_log->info("DL NAS: Sent Downlink NAS message\n"); + m_s1ap_log->console("DL NAS: Sent Downlink NAs Message\n"); m_pool->deallocate(nas_msg); m_pool->deallocate(reply_msg); @@ -472,15 +472,17 @@ s1ap::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, srslte: m_s1ap_log->console("UE Authentication Rejected. IMSI: %lu\n", ue_ctx->imsi); m_s1ap_log->warning("UE Authentication Rejected. IMSI: %lu\n", ue_ctx->imsi); - //TODO send back error reply + //Send back Athentication Reject m_s1ap_nas_transport.pack_authentication_reject(reply_msg, ue_ctx->enb_ue_s1ap_id, ue_ctx->mme_ue_s1ap_id); return false; } - m_s1ap_log->console("UE Authentication Accepted. IMSI: %lu\n", ue_ctx->imsi); - m_s1ap_log->info("UE Authentication Accepted. IMSI: %lu\n", ue_ctx->imsi); - - //Send Security Mode Command - m_s1ap_nas_transport.pack_security_mode_command(reply_msg, ue_ctx); + else + { + m_s1ap_log->console("UE Authentication Accepted. IMSI: %lu\n", ue_ctx->imsi); + m_s1ap_log->info("UE Authentication Accepted. IMSI: %lu\n", ue_ctx->imsi); + //Send Security Mode Command + m_s1ap_nas_transport.pack_security_mode_command(reply_msg, ue_ctx); + } return true; } diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 2400edc17..0d8ab035a 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -180,12 +180,12 @@ s1ap_nas_transport::pack_authentication_reject(srslte::byte_buffer_t *reply_msg, dw_nas->HandoverRestrictionList_present=false; dw_nas->SubscriberProfileIDforRFP_present=false; - LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT auth_rej; - LIBLTE_ERROR_ENUM err = liblte_mme_pack_authentication_request_msg(&auth_rej, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + LIBLTE_MME_AUTHENTICATION_REJECT_MSG_STRUCT auth_rej; + LIBLTE_ERROR_ENUM err = liblte_mme_pack_authentication_reject_msg(&auth_rej, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); if(err != LIBLTE_SUCCESS) { - m_s1ap_log->error("Error packing Athentication Request\n"); - m_s1ap_log->console("Error packing Athentication Request\n"); + m_s1ap_log->error("Error packing Athentication Reject\n"); + m_s1ap_log->console("Error packing Athentication Reject\n"); return false; } @@ -197,8 +197,8 @@ s1ap_nas_transport::pack_authentication_reject(srslte::byte_buffer_t *reply_msg, err = liblte_s1ap_pack_s1ap_pdu(&tx_pdu, (LIBLTE_BYTE_MSG_STRUCT *) reply_msg); if(err != LIBLTE_SUCCESS) { - m_s1ap_log->error("Error packing Athentication Reject\n"); - m_s1ap_log->console("Error packing Athentication Reject\n"); + m_s1ap_log->error("Error packing Dw NAS Transport: Athentication Reject\n"); + m_s1ap_log->console("Error packing Downlink NAS Transport: Athentication Reject\n"); return false; } From 46edf6feab35c20317634657f401ff46db95e570 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 13 Nov 2017 15:18:35 +0000 Subject: [PATCH 068/172] Small modification to parse config file. --- srsepc/epc.conf.example | 25 +++++++++++++++++++++++++ srsepc/src/main.cc | 20 ++++++++++++++++++++ srsepc/src/mme/mme.cc | 4 ++-- 3 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 srsepc/epc.conf.example diff --git a/srsepc/epc.conf.example b/srsepc/epc.conf.example new file mode 100644 index 000000000..16434ceee --- /dev/null +++ b/srsepc/epc.conf.example @@ -0,0 +1,25 @@ +##################################################################### +# srsEPC configuration file +##################################################################### + +##################################################################### +# MME configuration +# +# mme_code: 8-bit MME code identifies the MME within a group. +# mme_group: 16-bit MME group identifier. +# tac: 16-bit Tracking Area Code. +# mcc: Mobile Country Code +# mnc: Mobile Network Code +# mme_bindx_addr: IP subnet to listen for eNB S1 connnections +# +##################################################################### +[mme] +mme_code = 0x19 +mme_group = 0x0001 +tac = 0x0001 +mcc = 001 +mnc = 01 +mme_bind_addr = 127.0.0.0/24 + + + diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index 366ffaf5f..1627a216c 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -22,6 +22,7 @@ * */ #include +#include #include #include #include @@ -113,6 +114,25 @@ parse_args(all_args_t *args, int argc, char* argv[]) { cout << common << endl << general << endl; exit(0); } + + //Parsing Config File + if (!vm.count("config_file")) { + cout << "Error: Configuration file not provided" << endl; + cout << "Usage: " << argv[0] << " [OPTIONS] config_file" << endl << endl; + exit(0); + } else { + cout << "Reading configuration file " << config_file << "..." << endl; + ifstream conf(config_file.c_str(), ios::in); + if(conf.fail()) { + cout << "Failed to read configuration file " << config_file << " - exiting" << endl; + exit(1); + } + bpo::store(bpo::parse_config_file(conf, common), vm); + bpo::notify(vm); + } + + + //Concert hex strings { std::stringstream sstr; diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index a8629f2fc..8d45276e8 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -81,8 +81,8 @@ mme::init(mme_args_t* args, srslte::log_filter *s1ap_log) /*Init logger*/ m_s1ap_log = s1ap_log; - m_s1ap_log->info("MME Initialized\n"); - m_s1ap_log->console("MME Initialized\n"); + m_s1ap_log->info("MME Initialized. MCC: %d, MNC: %d\n",args->s1ap_args.mcc, args->s1ap_args.mnc); + m_s1ap_log->console("MME Initialized. \n"); return 0; } From 042cabc8a01e247531ead7ad5a39b36040f80f72 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 13 Nov 2017 16:42:41 +0000 Subject: [PATCH 069/172] Starting to add S-GW --- srsepc/conf/epc.conf | 23 -------- srsepc/hdr/sgw/sgw.h | 76 +++++++++++++++++++++++++ srsepc/src/CMakeLists.txt | 2 + srsepc/src/sgw/CMakeLists.txt | 23 ++++++++ srsepc/src/sgw/sgw.cc | 102 ++++++++++++++++++++++++++++++++++ 5 files changed, 203 insertions(+), 23 deletions(-) delete mode 100644 srsepc/conf/epc.conf create mode 100644 srsepc/hdr/sgw/sgw.h create mode 100644 srsepc/src/sgw/CMakeLists.txt create mode 100644 srsepc/src/sgw/sgw.cc diff --git a/srsepc/conf/epc.conf b/srsepc/conf/epc.conf deleted file mode 100644 index 1bc5d7648..000000000 --- a/srsepc/conf/epc.conf +++ /dev/null @@ -1,23 +0,0 @@ -##################################################################### -# srsEPC configuration file -##################################################################### - -##################################################################### -# MME configuration -# -# mme_code: 8-bit MME code identifies the MME within a group. -# mme_group: 16-bit MME group identifier. -# tac: 16-bit Tracking Area Code. -# mcc: Mobile Country Code -# mnc: Mobile Network Code -# mme_bindx_addr: IP subnet to listen for eNB S1 connnections -# -##################################################################### -[mme] -mme_code = 0x19 -mme_group = 0x0001 -phy_cell_id = 1 -tac = 0x0001 -mcc = 208 -mnc = 93 -mme_bindx_addr = 127.0.0.0/24 diff --git a/srsepc/hdr/sgw/sgw.h b/srsepc/hdr/sgw/sgw.h new file mode 100644 index 000000000..85faa4c21 --- /dev/null +++ b/srsepc/hdr/sgw/sgw.h @@ -0,0 +1,76 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +/****************************************************************************** + * File: sgw.h + * Description: Top-level S-GW class. Creates and links all + * interfaces and helpers. + *****************************************************************************/ + +#ifndef SGW_H +#define SGW_H + +#include +#include "srslte/common/log.h" +#include "srslte/common/logger_file.h" +#include "srslte/common/log_filter.h" +#include "srslte/common/buffer_pool.h" +#include "srslte/common/threads.h" + +namespace srsepc{ + +typedef struct { + std::string gtpc_bind_addr; +} sgw_args_t; + + +class sgw: + public thread +{ +public: + static sgw* get_instance(void); + static void cleanup(void); + int init(sgw_args_t* args, srslte::log_filter *sgw_log); + void stop(); + void run_thread(); + +private: + + sgw(); + virtual ~sgw(); + static sgw *m_instance; + + bool m_running; + srslte::byte_buffer_pool *m_pool; + + /*Logs*/ + srslte::log_filter *m_sgw_log; + +}; + +} // namespace srsepc + +#endif // SGW_H diff --git a/srsepc/src/CMakeLists.txt b/srsepc/src/CMakeLists.txt index d92c5201e..6ce5e44db 100644 --- a/srsepc/src/CMakeLists.txt +++ b/srsepc/src/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory(mme) add_subdirectory(hss) +add_subdirectory(sgw) # Link libstdc++ and libgcc if(BUILD_STATIC) @@ -16,6 +17,7 @@ endif (RPATH) add_executable(srsepc main.cc ) target_link_libraries(srsepc srsepc_mme srsepc_hss + srsepc_sgw srslte_upper srslte_common ${CMAKE_THREAD_LIBS_INIT} diff --git a/srsepc/src/sgw/CMakeLists.txt b/srsepc/src/sgw/CMakeLists.txt new file mode 100644 index 000000000..ba50e480c --- /dev/null +++ b/srsepc/src/sgw/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright 2013-2017 Software Radio Systems Limited +# +# This file is part of srsLTE +# +# srsLTE is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# srsLTE is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# A copy of the GNU Affero General Public License can be found in +# the LICENSE file in the top-level directory of this distribution +# and at http://www.gnu.org/licenses/. +# + +file(GLOB SOURCES "*.cc") +add_library(srsepc_sgw STATIC ${SOURCES}) +install(TARGETS srsepc_sgw DESTINATION ${LIBRARY_DIR}) diff --git a/srsepc/src/sgw/sgw.cc b/srsepc/src/sgw/sgw.cc new file mode 100644 index 000000000..6293b57d5 --- /dev/null +++ b/srsepc/src/sgw/sgw.cc @@ -0,0 +1,102 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include +#include +#include "sgw/sgw.h" + +namespace srsepc{ + +sgw* sgw::m_instance = NULL; +boost::mutex sgw_instance_mutex; + +sgw::sgw(): + m_running(false) +{ + m_pool = srslte::byte_buffer_pool::get_instance(); + return; +} + +sgw::~sgw() +{ + return; +} + +sgw* +sgw::get_instance(void) +{ + boost::mutex::scoped_lock lock(sgw_instance_mutex); + if(NULL == m_instance) { + m_instance = new sgw(); + } + return(m_instance); +} + +void +sgw::cleanup(void) +{ + boost::mutex::scoped_lock lock(sgw_instance_mutex); + if(NULL != m_instance) { + delete m_instance; + m_instance = NULL; + } +} + +int +sgw::init(sgw_args_t* args, srslte::log_filter *sgw_log) +{ + + m_sgw_log = sgw_log; + m_sgw_log->info("S-GW Initialized.\n"); + m_sgw_log->console("S-GW Initialized.\n"); + return 0; +} + +void +sgw::stop() +{ + if(m_running) + { + m_running = false; + thread_cancel(); + wait_thread_finish(); + } + return; +} + +void +sgw::run_thread() +{ + //Mark the thread as running + m_running=true; + while (m_running) + { + sleep(1); + } + return; +} + +} //namespace srsepc From 99f6ffe63b8187ec18438ef9b542e725cc5b56b7 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 15 Nov 2017 16:39:25 +0000 Subject: [PATCH 070/172] Starting to add code to create the GTP-C messages. --- lib/include/srslte/asn1/gtpc.h | 177 +++++++++++++++++++++++++++++++++ lib/src/asn1/CMakeLists.txt | 1 + lib/src/asn1/gtpc.cc | 73 ++++++++++++++ srsepc/src/mme/s1ap.cc | 2 + 4 files changed, 253 insertions(+) create mode 100644 lib/include/srslte/asn1/gtpc.h create mode 100644 lib/src/asn1/gtpc.cc diff --git a/lib/include/srslte/asn1/gtpc.h b/lib/include/srslte/asn1/gtpc.h new file mode 100644 index 000000000..754bd29b7 --- /dev/null +++ b/lib/include/srslte/asn1/gtpc.h @@ -0,0 +1,177 @@ +/*ection COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsUE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsUE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ +#include + +#ifdef GTPC_V2 +#define GTPC_V2 + +namespace srslte{ + +/*GTP-C Version*/ +const uint8_t GTPC_V2 = 2; + +/**************************************************************** + * + * GTP-C Message Types + * Ref: TS 29.274 Table 6.1-1 + * + ****************************************************************/ +const uint8_t GTPC_MSG_TYPE_RESERVED = 0; +const uint8_t GTPC_MSG_TYPE_ECHO_REQUEST = 1; +const uint8_t GTPC_MSG_TYPE_ECHO_RESPONSE = 2; +const uint8_t GTPC_MSG_TYPE_VERSION_SUPPORT = 3; +//4-24 Reserved for S101 +//25-31 Reserved for Sv interface +//SGSN/MME/ePDG to PGW (S4/S11, S5/S8, S2b) +const uint8_t GTPC_MSG_TYPE_CREATE_SESSION_REQUEST = 32; +const uint8_t GTPC_MSG_TYPE_CREATE_SESSION_RESPONSE = 33; +const uint8_t GTPC_MSG_TYPE_DELETE_SESSION_REQUEST = 36; +const uint8_t GTPC_MSG_TYPE_DELETE_SESSION_RESPONSE = 37; +//SGSN/MME to PGW (S4/S11, S5/S8) +const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_REQUEST = 34; +const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_RESPONSE = 35; +const uint8_t GTPC_MSG_TYPE_CHANGE_NOTIFICATION_REQUEST = 38; +const uint8_t GTPC_MSG_TYPE_CHANGE_NOTIFICATION_RESPONSE = 39; +//40 - 63 for future use +const uint8_t GTPC_MSG_TYPE_RESUME_NOTIFICATION = 164; +const uint8_t GTPC_MSG_TYPE_RESUME_ACKNOWLEDGE = 165; +//Messages without explicit response +const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_COMMAND = 64; //(MME/SGSN/ePDG to PGW – S11/S4, S5/S8, S2b) +const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_FAILURE_INDICATION = 65; //(PGW to MME/SGSN/ePDG – S5/S8, S11/S4, S2b) +const uint8_t GTPC_MSG_TYPE_DELETE_BEARER_COMMAND = 66; //(MME/SGSN to PGW – S11/S4, S5/S8) +const uint8_t GTPC_MSG_TYPE_DELETE_BEARER_FAILURE_INDICATION = 67; //(PGW to MME/SGSN – S5/S8, S11/S4)) +const uint8_t GTPC_MSG_TYPE_BEARER_RESOURCE_COMMAND = 68; //(MME/SGSN to PGW – S11/S4, S5/S8) +const uint8_t GTPC_MSG_TYPE_BEARER_RESOURCE_FAILURE_INDICATION = 69; //(PGW to MME/SGSN – S5/S8, S11/S4) +const uint8_t GTPC_MSG_TYPE_DOWNLINK_DATA_NOTIFICATION_FAILURE_INDICATION = 70; //(SGSN/MME to SGW – S4/S11) +const uint8_t GTPC_MSG_TYPE_TRACE_SESSION_ACTIVATION = 71; //(MME/SGSN/ePDG to PGW – S11/S4, S5/S8, S2b) +const uint8_t GTPC_MSG_TYPE_TRACE_SESSION_DEACTIVATION = 72; //(MME/SGSN/ePDG to PGW – S11/S4, S5/S8, S2b) +const uint8_t GTPC_MSG_TYPE_STOP_PAGING_INDICATION = 73; //(SGW to MME/SGSN – S11/S4) +//74-94 For future use +//P-GW to SGSN/MME/ePDG +const uint8_t GTPC_MSG_TYPE_CREATE_BEARER_REQUEST = 95; +const uint8_t GTPC_MSG_TYPE_CREATE_BEARER_RESPONSE = 96; +const uint8_t GTPC_MSG_TYPE_UPDATE_BEARER_REQUEST = 97; +const uint8_t GTPC_MSG_TYPE_UPDATE_BEARER_RESPONSE = 98; +const uint8_t GTPC_MSG_TYPE_DELETE_BEARER_REQUEST = 99; +const uint8_t GTPC_MSG_TYPE_DELETE_BEARER_RESPONSE = 100; +//PGW to MME, MME to PGW, SGW to PGW, SGW to MME, PGW to ePDG, ePDG to PGW (S5/S8, S11, S2b) +const uint8_t GTPC_MSG_TYPE_DELETE_PDN_CONNECTION_SET_REQUEST = 101; +const uint8_t GTPC_MSG_TYPE_DELETE_PDN_CONNECTION_SET_RESPONSE = 102; +//103-127 For future use +//MME to MME, SGSN to MME, MME to SGSN, SGSN to SGSN (S3/S10/S16) +const uint8_t GTPC_MSG_TYPE_IDENTIFICATION_REQUEST = 128; +const uint8_t GTPC_MSG_TYPE_IDENTIFICATION_RESPONSE = 129; +const uint8_t GTPC_MSG_TYPE_CONTEXT_REQUEST = 130; +const uint8_t GTPC_MSG_TYPE_CONTEXT_RESPONSE = 131; +const uint8_t GTPC_MSG_TYPE_CONTEXT_ACKNOWLEDGE = 132; +const uint8_t GTPC_MSG_TYPE_FORWARD_RELOCATION_REQUEST = 133; +const uint8_t GTPC_MSG_TYPE_FORWARD_RELOCATION_RESPONSE = 134; +const uint8_t GTPC_MSG_TYPE_FORWARD_RELOCATION_COMPLETE_NOTIFICATION = 135; +const uint8_t GTPC_MSG_TYPE_FORWARD_RELOCATION_COMPLETE_ACKNOWLEDGE = 136; +const uint8_t GTPC_MSG_TYPE_FORWARD_ACCESS_CONTEXT_NOTIFICATION = 137; +const uint8_t GTPC_MSG_TYPE_FORWARD_ACCESS_CONTEXT_ACKNOWLEDGE = 138; +const uint8_t GTPC_MSG_TYPE_RELOCATION_CANCEL_REQUEST = 139; +const uint8_t GTPC_MSG_TYPE_RELOCATION_CANCEL_RESPONSE = 140; +const uint8_t GTPC_MSG_TYPE_CONFIGURATION_TRANSFER_TUNNEL = 141; +//142 - 148 For future use +const uint8_t GTPC_MSG_TYPE_RAN_INFORMATION_RELAY = 152; +//SGSN to MME, MME to SGSN (S3) +const uint8_t GTPC_MSG_TYPE_DETACH_NOTIFICATION = 149; +const uint8_t GTPC_MSG_TYPE_DETACH_ACKNOWLEDGE = 150; +const uint8_t GTPC_MSG_TYPE_CS_PAGING_INDICATION = 151; +const uint8_t GTPC_MSG_TYPE_ALERT_MME_NOTIFICATION = 153; +const uint8_t GTPC_MSG_TYPE_ALERT_MME_ACKNOWLEDGE = 154; +const uint8_t GTPC_MSG_TYPE_UE_ACTIVITY_NOTIFICATION = 155; +const uint8_t GTPC_MSG_TYPE_UE_ACTIVITY_ACKNOWLEDGE = 156; +//157 - 159 For future use +//GSN/MME to SGW, SGSN to MME (S4/S11/S3) SGSN to SGSN (S16), SGW to PGW (S5/S8) +const uint8_t GTPC_MSG_TYPE_SUSPEND_NOTIFICATION = 162; +const uint8_t GTPC_MSG_TYPE_SUSPEND_ACKNOWLEDGE = 163; +//SGSN/MME to SGW (S4/S11) +const uint8_t GTPC_MSG_TYPE_CREATE_FORWARDING_TUNNEL_REQUEST = 160; +const uint8_t GTPC_MSG_TYPE_CREATE_FORWARDING_TUNNEL_RESPONSE = 161; +const uint8_t GTPC_MSG_TYPE_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST = 166; +const uint8_t GTPC_MSG_TYPE_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE = 167; +const uint8_t GTPC_MSG_TYPE_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST = 168; +const uint8_t GTPC_MSG_TYPE_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE = 169; +const uint8_t GTPC_MSG_TYPE_RELEASE_ACCESS_BEARERS_REQUEST = 170; +const uint8_t GTPC_MSG_TYPE_RELEASE_ACCESS_BEARERS_RESPONSE = 171; +//172 - 175 For future use +//SGW to SGSN/MME (S4/S11) +const uint8_t GTPC_MSG_TYPE_DOWNLINK_DATA_NOTIFICATION = 176; +const uint8_t GTPC_MSG_TYPE_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE = 177; +const uint8_t GTPC_MSG_TYPE_PGW_RESTART_NOTIFICATION = 179; +const uint8_t GTPC_MSG_TYPE_PGW_RESTART_NOTIFICATION_ACKNOWLEDGE = 180; +//SGW to SGSN (S4) +//178 Reserved. Allocated in earlier version of the specification. +//181 -189 For future use +//SGW to PGW, PGW to SGW (S5/S8) +const uint8_t GTPC_MSG_TYPE_UPDATE_PDN_CONNECTION_SET_REQUEST = 200; +const uint8_t GTPC_MSG_TYPE_UPDATE_PDN_CONNECTION_SET_RESPONSE = 201; +//For future use +//MME to SGW (S11) +const uint8_t GTPC_MSG_TYPE_MODIFY_ACCESS_BEARERS_REQUEST = 211; +const uint8_t GTPC_MSG_TYPE_MODIFY_ACCESS_BEARERS_RESPONSE = 212; +//For future use +//MBMS GW to MME/SGSN (Sm/Sn) +const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_START_REQUEST = 231; +const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_START_RESPONSE = 232; +const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_UPDATE_REQUEST = 233; +const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_UPDATE_RESPONSE = 234; +const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_STOP_REQUEST = 235; +const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_STOP_RESPONSE = 236; +//For future use +//Other +//240 - 255 For future use + +/**************************************************************************** + * GTP-C v2 Header + * Ref: 3GPP TS 29.274 v10.14.0 Section 5 + * + * | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | + * + * 1 | Version | P | T | S | S | S | + * 2 | Message Type | + * 3 | Length (1st Octet) | + * 4 | Length (2nd Octet) | + * m | If T=1, TEID (1st Octet) | + * m+1 | If T=1, TEID (2nd Octet) | + * m+2 | If T=1, TEID (3st Octet) | + * m+3 | If T=1, TEID (4st Octet) | + * n | Sequence | + * n+1 | Sequence | + * n+2 | Sequence | + * n+3 | Spare | + ***************************************************************************/ +typedef struct gtpc_header +{ + uint8_t version; + bool piggyback; + bool tied_present; + enum gtpc_msg_type msg_type; + uint64_t teid; + uint64_t sequence; +} gtpc_header_t; + +}; diff --git a/lib/src/asn1/CMakeLists.txt b/lib/src/asn1/CMakeLists.txt index d3c52b807..caddb384c 100644 --- a/lib/src/asn1/CMakeLists.txt +++ b/lib/src/asn1/CMakeLists.txt @@ -24,5 +24,6 @@ add_library(srslte_asn1 STATIC liblte_rrc.cc liblte_mme.cc liblte_s1ap.cc + gtpc.cc ) install(TARGETS srslte_asn1 DESTINATION ${LIBRARY_DIR}) diff --git a/lib/src/asn1/gtpc.cc b/lib/src/asn1/gtpc.cc new file mode 100644 index 000000000..8bbad47df --- /dev/null +++ b/lib/src/asn1/gtpc.cc @@ -0,0 +1,73 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsUE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsUE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ +#include + +namespace srslte{ + + +enum gtpc_version +{ + GTPC_V1 = 1, + GTPC_V2 +}; + +enum gtpc_msg_type +{ + RESERVED = 0, + ECHO_REQUEST = 1 +}; + +/**************************************************************************** + * GTP-C Header + * Ref: 3GPP TS 29.274 v10.14.0 Section 5 + * + * | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | + * + * 1 | Version | P | T | S | S | S | + * 2 | Message Type | + * 3 | Length (1st Octet) | + * 4 | Length (2nd Octet) | + * m | If T=1, TEID (1st Octet) | + * m+1 | If T=1, TEID (2nd Octet) | + * m+2 | If T=1, TEID (3st Octet) | + * m+3 | If T=1, TEID (4st Octet) | + * n | Sequence | + * n+1 | Sequence | + * n+2 | Sequence | + * n+3 | Spare | + ***************************************************************************/ + +typedef struct gtpc_header +{ + enum gtpc_version version; + bool piggyback; + bool tied_present; + enum gtpc_msg_type msg_type; + uint64_t teid; + uint64_t sequence; +} gtpc_header_t; + +}; diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 3f1a461cf..16ebd19e1 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -482,6 +482,8 @@ s1ap::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, srslte: m_s1ap_log->info("UE Authentication Accepted. IMSI: %lu\n", ue_ctx->imsi); //Send Security Mode Command m_s1ap_nas_transport.pack_security_mode_command(reply_msg, ue_ctx); + + //m_gtpc->send_create_session_request(ue_ctx->imsi); } return true; } From 04d3a3f8ca69649e1a45aff21aa414d7bbcc9307 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 15 Nov 2017 19:10:14 +0000 Subject: [PATCH 071/172] Continue to work on pakcing the create session request message --- lib/include/srslte/asn1/gtpc.h | 48 +++++++++++++++++++++++++++++++++- lib/src/asn1/gtpc.cc | 13 --------- 2 files changed, 47 insertions(+), 14 deletions(-) diff --git a/lib/include/srslte/asn1/gtpc.h b/lib/include/srslte/asn1/gtpc.h index 754bd29b7..7c2cb7040 100644 --- a/lib/include/srslte/asn1/gtpc.h +++ b/lib/include/srslte/asn1/gtpc.h @@ -164,14 +164,60 @@ const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_STOP_RESPONSE = 236; * n+2 | Sequence | * n+3 | Spare | ***************************************************************************/ + typedef struct gtpc_header { uint8_t version; bool piggyback; bool tied_present; - enum gtpc_msg_type msg_type; + uint8_t msg_type; uint64_t teid; uint64_t sequence; } gtpc_header_t; + +/**************************************************************************** + * + * GTP-C v2 Create Session Request + * Ref: 3GPP TS 29.274 v10.14.0 Table 7.2.1-1 + * + ***************************************************************************/ +typedef struct gtpc_create_session_request +{ + uint64_t imsi; + uint64_t msisdn; + uint64_t mei; + struct user_location_info_ uli; + struct serving_network_ serving_network; + enum rat_type_ rat_type; + struct indication_flags_ indication_flags; + struct fteid_ sender_f_teid; + struct fteid_ pgw_addr; + uint64_t apn; + enum selection_mode_ selection_mode; + enum pdn_type_ pdn_type; + struct pdn_addr_alloc_ pdn_addr_alloc; + maximum apn_restriction; + apn_ambr; + linked_eps_bearer_id; + pco; + bearer_context_created; + bearer_context_deleted; + trace_information; + recovery; + mme_fq_csid; + sgw_fq_csid; + epdg_fq_csid; + ue_time_zone; + uci; + charging_caracteristics; + mme_ldn; + sgw_ldn; + epdg_ldn; + signalling_priority_indication; + apco; + bool ext; +} gtpc_create_session_request_t; + + }; diff --git a/lib/src/asn1/gtpc.cc b/lib/src/asn1/gtpc.cc index 8bbad47df..6ef2de14f 100644 --- a/lib/src/asn1/gtpc.cc +++ b/lib/src/asn1/gtpc.cc @@ -27,19 +27,6 @@ namespace srslte{ - -enum gtpc_version -{ - GTPC_V1 = 1, - GTPC_V2 -}; - -enum gtpc_msg_type -{ - RESERVED = 0, - ECHO_REQUEST = 1 -}; - /**************************************************************************** * GTP-C Header * Ref: 3GPP TS 29.274 v10.14.0 Section 5 From 542edb988afab9746dd596cdfccc3e834bfa295e Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 16 Nov 2017 21:07:55 +0000 Subject: [PATCH 072/172] Added GTPC ie and msg type definitions --- lib/include/srslte/asn1/gtpc.h | 131 +++++++++++++++++---------- lib/include/srslte/asn1/gtpc_ies.h | 136 +++++++++++++++++++++++++++++ lib/src/asn1/gtpc.cc | 35 ++------ 3 files changed, 227 insertions(+), 75 deletions(-) create mode 100644 lib/include/srslte/asn1/gtpc_ies.h diff --git a/lib/include/srslte/asn1/gtpc.h b/lib/include/srslte/asn1/gtpc.h index 7c2cb7040..0b6d976f3 100644 --- a/lib/include/srslte/asn1/gtpc.h +++ b/lib/include/srslte/asn1/gtpc.h @@ -1,4 +1,4 @@ -/*ection COPYRIGHT +/* \section COPYRIGHT * * Copyright 2013-2017 Software Radio Systems Limited * @@ -21,10 +21,11 @@ * and at http://www.gnu.org/licenses/. * */ +#ifndef GTPC_V2_H +#define GTPC_V2_H + #include -#ifdef GTPC_V2 -#define GTPC_V2 namespace srslte{ @@ -34,7 +35,7 @@ const uint8_t GTPC_V2 = 2; /**************************************************************** * * GTP-C Message Types - * Ref: TS 29.274 Table 6.1-1 + * Ref: TS 29.274 v10.14.0 Table 6.1-1 * ****************************************************************/ const uint8_t GTPC_MSG_TYPE_RESERVED = 0; @@ -57,16 +58,16 @@ const uint8_t GTPC_MSG_TYPE_CHANGE_NOTIFICATION_RESPONSE = 39; const uint8_t GTPC_MSG_TYPE_RESUME_NOTIFICATION = 164; const uint8_t GTPC_MSG_TYPE_RESUME_ACKNOWLEDGE = 165; //Messages without explicit response -const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_COMMAND = 64; //(MME/SGSN/ePDG to PGW – S11/S4, S5/S8, S2b) -const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_FAILURE_INDICATION = 65; //(PGW to MME/SGSN/ePDG – S5/S8, S11/S4, S2b) -const uint8_t GTPC_MSG_TYPE_DELETE_BEARER_COMMAND = 66; //(MME/SGSN to PGW – S11/S4, S5/S8) -const uint8_t GTPC_MSG_TYPE_DELETE_BEARER_FAILURE_INDICATION = 67; //(PGW to MME/SGSN – S5/S8, S11/S4)) -const uint8_t GTPC_MSG_TYPE_BEARER_RESOURCE_COMMAND = 68; //(MME/SGSN to PGW – S11/S4, S5/S8) -const uint8_t GTPC_MSG_TYPE_BEARER_RESOURCE_FAILURE_INDICATION = 69; //(PGW to MME/SGSN – S5/S8, S11/S4) -const uint8_t GTPC_MSG_TYPE_DOWNLINK_DATA_NOTIFICATION_FAILURE_INDICATION = 70; //(SGSN/MME to SGW – S4/S11) -const uint8_t GTPC_MSG_TYPE_TRACE_SESSION_ACTIVATION = 71; //(MME/SGSN/ePDG to PGW – S11/S4, S5/S8, S2b) -const uint8_t GTPC_MSG_TYPE_TRACE_SESSION_DEACTIVATION = 72; //(MME/SGSN/ePDG to PGW – S11/S4, S5/S8, S2b) -const uint8_t GTPC_MSG_TYPE_STOP_PAGING_INDICATION = 73; //(SGW to MME/SGSN – S11/S4) +const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_COMMAND = 64; //(MME/SGSN/ePDG to PGW – S11/S4, S5/S8, S2b) +const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_FAILURE_INDICATION = 65; //(PGW to MME/SGSN/ePDG – S5/S8, S11/S4, S2b) +const uint8_t GTPC_MSG_TYPE_DELETE_BEARER_COMMAND = 66; //(MME/SGSN to PGW – S11/S4, S5/S8) +const uint8_t GTPC_MSG_TYPE_DELETE_BEARER_FAILURE_INDICATION = 67; //(PGW to MME/SGSN – S5/S8, S11/S4)) +const uint8_t GTPC_MSG_TYPE_BEARER_RESOURCE_COMMAND = 68; //(MME/SGSN to PGW – S11/S4, S5/S8) +const uint8_t GTPC_MSG_TYPE_BEARER_RESOURCE_FAILURE_INDICATION = 69; //(PGW to MME/SGSN – S5/S8, S11/S4) +const uint8_t GTPC_MSG_TYPE_DOWNLINK_DATA_NOTIFICATION_FAILURE_INDICATION = 70; //(SGSN/MME to SGW – S4/S11) +const uint8_t GTPC_MSG_TYPE_TRACE_SESSION_ACTIVATION = 71; //(MME/SGSN/ePDG to PGW – S11/S4, S5/S8, S2b) +const uint8_t GTPC_MSG_TYPE_TRACE_SESSION_DEACTIVATION = 72; //(MME/SGSN/ePDG to PGW – S11/S4, S5/S8, S2b) +const uint8_t GTPC_MSG_TYPE_STOP_PAGING_INDICATION = 73; //(SGW to MME/SGSN – S11/S4) //74-94 For future use //P-GW to SGSN/MME/ePDG const uint8_t GTPC_MSG_TYPE_CREATE_BEARER_REQUEST = 95; @@ -108,7 +109,7 @@ const uint8_t GTPC_MSG_TYPE_UE_ACTIVITY_ACKNOWLEDGE = 156; //GSN/MME to SGW, SGSN to MME (S4/S11/S3) SGSN to SGSN (S16), SGW to PGW (S5/S8) const uint8_t GTPC_MSG_TYPE_SUSPEND_NOTIFICATION = 162; const uint8_t GTPC_MSG_TYPE_SUSPEND_ACKNOWLEDGE = 163; -//SGSN/MME to SGW (S4/S11) +//SGSN/MME to SGW (S4/S11) const uint8_t GTPC_IE_TYPE_ const uint8_t GTPC_MSG_TYPE_CREATE_FORWARDING_TUNNEL_REQUEST = 160; const uint8_t GTPC_MSG_TYPE_CREATE_FORWARDING_TUNNEL_RESPONSE = 161; const uint8_t GTPC_MSG_TYPE_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST = 166; @@ -184,40 +185,74 @@ typedef struct gtpc_header ***************************************************************************/ typedef struct gtpc_create_session_request { - uint64_t imsi; - uint64_t msisdn; - uint64_t mei; - struct user_location_info_ uli; - struct serving_network_ serving_network; - enum rat_type_ rat_type; - struct indication_flags_ indication_flags; - struct fteid_ sender_f_teid; - struct fteid_ pgw_addr; - uint64_t apn; - enum selection_mode_ selection_mode; - enum pdn_type_ pdn_type; - struct pdn_addr_alloc_ pdn_addr_alloc; - maximum apn_restriction; - apn_ambr; - linked_eps_bearer_id; - pco; - bearer_context_created; - bearer_context_deleted; - trace_information; - recovery; - mme_fq_csid; - sgw_fq_csid; - epdg_fq_csid; - ue_time_zone; - uci; - charging_caracteristics; - mme_ldn; - sgw_ldn; - epdg_ldn; - signalling_priority_indication; - apco; - bool ext; + bool imsi_present; + uint64_t imsi; // C + bool msidn_present; + uint64_t msisdn; // C + bool mei_present; + uint64_t mei; // C/CO + bool user_location_info_present; + struct user_location_info_ uli; // C/CO + bool serving_network_present; + struct serving_network_ serving_network; // C/CO + + enum rat_type_ rat_type; // M + bool indication_flags_present; + struct indication_flags_ indication_flags; // C + + struct fteid_ sender_f_teid; // M + bool pgw_addr_present; + struct fteid_ pgw_addr; // C + + uint64_t apn; // M + bool selection_mode_present; + enum selection_mode_ selection_mode; // C/CO + bool pdn_type_present; + enum pdn_type_ pdn_type; // C + bool pdn_addr_alloc_present; + struct pdn_addr_alloc_ pdn_addr_alloc; // C/CO + bool max_apn_restriction_present; + enum apn_restriction_ max_apn_restriction; // C + bool apn_ambr_present; + struct ambr_ apn_ambr; // C + bool linked_eps_bearer_id_present; + uint8_t linked_eps_bearer_id; // C + bool pco_present; + uint8_t pco; // C + + struct bearer_context_ bearer_context_created; // M + bool bearer_context_deleted_present; + struct bearer_context_ bearer_context_deleted; // C + bool trace_information_present; + struct trace_infromation_ trace_information; // C + bool recovery_present + uint8_t recovery; // C + bool mme_fq_csid_present; + struct fq_csid_ mme_fq_csid; // C + bool sgw_fq_csid_present; + struct fq_csid_ sgw_fq_csid; // C + bool epdg_fq_csid_present; + struct fq_csid_ epdg_fq_csid; // C + bool ue_time_zone_present; + struct ue_time_zone_ ue_time_zone; // CO + bool uci_present; + struct uci_ uci; // CO + bool charging_caracteristics_present; + enum charging_characteristics_ charging_caracteristics; // O + bool mme_ldn_present; + uint8_t mme_ldn[LDN_MAX_SIZE]; // O + bool sgw_ldn_present; + uint8_t sgw_ldn[LDN_MAX_SIZE]; // O + bool epgd_ldn_present; + uint8_t epdg_ldn[LDN_MAX_SIZE]; // O + bool signaling_priority_indication; + enum signalling_priority_indication_ spi; // CO + bool acpo_present; + uint8_t apco; // CO + bool ext; // O } gtpc_create_session_request_t; }; + +#endif diff --git a/lib/include/srslte/asn1/gtpc_ies.h b/lib/include/srslte/asn1/gtpc_ies.h new file mode 100644 index 000000000..be24a2da6 --- /dev/null +++ b/lib/include/srslte/asn1/gtpc_ies.h @@ -0,0 +1,136 @@ +/* \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsUE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsUE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + + +/**************************************************************** + * + * GTP-C IE Types + * Ref: TS 29.274 v10.14.0 Table 8.1-1 + * + ****************************************************************/ + +const uint8_t GTPC_IE_TYPE_RESERVED = 0; +const uint8_t GTPC_IE_TYPE_IMSI = 1; +const uint8_t GTPC_IE_TYPE_CAUSE = 2; +const uint8_t GTPC_IE_TYPE_RECOVERY = 3; +//4 to 50 RESERVED_FOR_S101_INTERFACE +const uint8_t GTPC_IE_TYPE_STN_SR = 51 +//52 to 70 RESERVED_FOR_SV_INTERFACE +const uint8_t GTPC_IE_TYPE_APN = 71; +const uint8_t GTPC_IE_TYPE_AMBR = 72; +const uint8_t GTPC_IE_TYPE_EBI = 73; +const uint8_t GTPC_IE_TYPE_IP_ADDRESS = 74; +const uint8_t GTPC_IE_TYPE_MEI = 75; +const uint8_t GTPC_IE_TYPE_MSISDN = 76; +const uint8_t GTPC_IE_TYPE_INDICATION = 77; +const uint8_t GTPC_IE_TYPE_PCO = 78; +const uint8_t GTPC_IE_TYPE_PDN_ADDRESS_ALLOCATION = 79; +const uint8_t GTPC_IE_TYPE_BEARER_QOS = 80; +const uint8_t GTPC_IE_TYPE_FLOW_QOS = 81; +const uint8_t GTPC_IE_TYPE_RAT_TYPE = 82; +const uint8_t GTPC_IE_TYPE_SERVING_NETWORK = 83; +const uint8_t GTPC_IE_TYPE_BEARER_TFT = 84; +const uint8_t GTPC_IE_TYPE_TAD = 85; +const uint8_t GTPC_IE_TYPE_ULI = 86; +const uint8_t GTPC_IE_TYPE_F_TEID = 87; +const uint8_t GTPC_IE_TYPE_TMSI = 88; +const uint8_t GTPC_IE_TYPE_GLOBAL_CN_ID = 89; +const uint8_t GTPC_IE_TYPE_S103_PDN_DATA_FORWARDING_INFO = 90; +const uint8_t GTPC_IE_TYPE_S1_U_DATA_FORWARDING_INFO = 91; +const uint8_t GTPC_IE_TYPE_DELAY_VALUE = 92; +const uint8_t GTPC_IE_TYPE_BEARER_CONTEXT = 93; +const uint8_t GTPC_IE_TYPE_CHARGING_ID = 94; +const uint8_t GTPC_IE_TYPE_CHARGING_CHARACTERISTICS = 95; +const uint8_t GTPC_IE_TYPE_TRACE_INFORMATION = 96; +const uint8_t GTPC_IE_TYPE_BEARER_FLAGS = 97; +const uint8_t GTPC_IE_TYPE_RESERVED = 98; +const uint8_t GTPC_IE_TYPE_PDN_TYPE = 99; +const uint8_t GTPC_IE_TYPE_PROCEDURE_TRANSACTION_ID = 100; +const uint8_t GTPC_IE_TYPE_DRX_PARAMETER = 101; +const uint8_t GTPC_IE_TYPE_RESERVED = 102; +const uint8_t GTPC_IE_TYPE_MM_CONTEXT_GSM_KEY_AND_TRIPLETS = 103; +const uint8_t GTPC_IE_TYPE_MM_CONTEXT_UMTS_KEY_USED_CIPHER_AND_QUINTUPLETS = 104; +const uint8_t GTPC_IE_TYPE_MM_CONTEXT_GSM_KEY_USED_CIPHER_AND_QUINTUPLETS = 105; +const uint8_t GTPC_IE_TYPE_MM_CONTEXT_UMTS_KEY_AND_QUINTUPLETS = 106; +const uint8_t GTPC_IE_TYPE_MM_CONTEXT_EPS_SECURITY_CONTEXT_QUADRUPLETS_AND_QUINTUPLETS = 107; +const uint8_t GTPC_IE_TYPE_MM_CONTEXT_UMTS_KEY_QUADRUPLETS_AND_QUINTUPLETS = 108; +const uint8_t GTPC_IE_TYPE_PDN_CONNECTION = 109; +const uint8_t GTPC_IE_TYPE_PDU_NUMBERS = 110; +const uint8_t GTPC_IE_TYPE_P_TMSI = 111; +const uint8_t GTPC_IE_TYPE_P_TMSI_SIGNATURE = 112; +const uint8_t GTPC_IE_TYPE_HOP_COUNTER = 113; +const uint8_t GTPC_IE_TYPE_UE_TIME_ZONE = 114 +const uint8_t GTPC_IE_TYPE_TRACE_REFERENCE = 115; +const uint8_t GTPC_IE_TYPE_COMPLETE_REQUEST_MESSAGE = 116; +const uint8_t GTPC_IE_TYPE_GUTI = 117; +const uint8_t GTPC_IE_TYPE_F_CONTAINER = 118; +const uint8_t GTPC_IE_TYPE_F_CAUSE = 119; +const uint8_t GTPC_IE_TYPE_SELECTED_PLMN_ID = 120; +const uint8_t GTPC_IE_TYPE_TARGET_IDENTIFICATION = 121; +const uint8_t GTPC_IE_TYPE_RESERVED = 122; +const uint8_t GTPC_IE_TYPE_PACKET_FLOW_ID = 123; +const uint8_t GTPC_IE_TYPE_RAB_CONTEXT = 124; +const uint8_t GTPC_IE_TYPE_SOURCE_RNC_PDCP_CONTEXT_INFO = 125; +const uint8_t GTPC_IE_TYPE_UDP_SOURCE_PORT_NUMBER = 126; +const uint8_t GTPC_IE_TYPE_APN_RESTRICTION = 127; +const uint8_t GTPC_IE_TYPE_SELECTION_MODE = 128; +const uint8_t GTPC_IE_TYPE_SOURCE_IDENTIFICATION = 129; +//130 RESERVED +const uint8_t GTPC_IE_TYPE_CHANGE_REPORTING_ACTION = 131; +const uint8_t GTPC_IE_TYPE_FQ_CSID = 132; +const uint8_t GTPC_IE_TYPE_CHANNEL_NEEDED = 133; +const uint8_t GTPC_IE_TYPE_EMLPP_PRIORITY = 134; +const uint8_t GTPC_IE_TYPE_NODE_TYPE = 135; +const uint8_t GTPC_IE_TYPE_FQDN = 136; +const uint8_t GTPC_IE_TYPE_TI = 137; +const uint8_t GTPC_IE_TYPE_MBMS_SESSION_DURATION = 138; +const uint8_t GTPC_IE_TYPE_MBMS_SERVICE_AREA = 139; +const uint8_t GTPC_IE_TYPE_MBMS_SESSION_IDENTIFIER = 140; +const uint8_t GTPC_IE_TYPE_MBMS_FLOW_IDENTIFIER = 141; +const uint8_t GTPC_IE_TYPE_MBMS_IP_MULTICAST_DISTRIBUTION = 142; +const uint8_t GTPC_IE_TYPE_MBMS_DISTRIBUTION_ACKNOWLEDGE = 143; +const uint8_t GTPC_IE_TYPE_RFSP_INDEX = 144; +const uint8_t GTPC_IE_TYPE_UCI = 145; +const uint8_t GTPC_IE_TYPE_CSG_INFORMATION_REPORTING_ACTION = 146; +const uint8_t GTPC_IE_TYPE_CSG_ID = 147; +const uint8_t GTPC_IE_TYPE_CMI = 148; +const uint8_t GTPC_IE_TYPE_SERVICE_INDICATOR = 149; +const uint8_t GTPC_IE_TYPE_DETACH_TYPE = 150; +const uint8_t GTPC_IE_TYPE_LDN = 151; +const uint8_t GTPC_IE_TYPE_NODE_FEATURES = 152; +const uint8_t GTPC_IE_TYPE_MBMS_TIME_TO_DATA_TRANSFER = 153; +const uint8_t GTPC_IE_TYPE_THROTTLING =154; +const uint8_t GTPC_IE_TYPE_ARP = 155; +const uint8_t GTPC_IE_TYPE_EPC_TIMER = 156; +const uint8_t GTPC_IE_TYPE_SIGNALLING_PRIORITY_INDICATION = 157; +const uint8_t GTPC_IE_TYPE_TMGI = 158; +const uint8_t GTPC_IE_TYPE_ADDITIONAL_MM_CONTEXT_FOR_SRVCC = 159; +const uint8_t GTPC_IE_TYPE_ADDITIONAL_FLAGS_FOR_SRVCC = 160; +//161 RESERVED +const uint8_t GTPC_IE_TYPE_MDT_CONFIGURATION = 162; +const uint8_t GTPC_IE_TYPE_APCO = 163; +//164 RESERVED +const uint8_t GTPC_IE_TYPE_CHANGE_TO_REPORT_FLAGS = 165; +//168 TO 254 SPARE. FOR FUTURE USE. +const uint8_t GTPC_IE_TYPE_PRIVATE_EXTENSION = 255; diff --git a/lib/src/asn1/gtpc.cc b/lib/src/asn1/gtpc.cc index 6ef2de14f..25d52c6d0 100644 --- a/lib/src/asn1/gtpc.cc +++ b/lib/src/asn1/gtpc.cc @@ -24,37 +24,18 @@ * */ #include +#include "srslte/asn1/gtpc.h" + namespace srslte{ -/**************************************************************************** - * GTP-C Header - * Ref: 3GPP TS 29.274 v10.14.0 Section 5 - * - * | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | - * - * 1 | Version | P | T | S | S | S | - * 2 | Message Type | - * 3 | Length (1st Octet) | - * 4 | Length (2nd Octet) | - * m | If T=1, TEID (1st Octet) | - * m+1 | If T=1, TEID (2nd Octet) | - * m+2 | If T=1, TEID (3st Octet) | - * m+3 | If T=1, TEID (4st Octet) | - * n | Sequence | - * n+1 | Sequence | - * n+2 | Sequence | - * n+3 | Spare | - ***************************************************************************/ -typedef struct gtpc_header +int +gtpc_pack_create_session_request(gtpc_create_session_request_t, srslte::byte_buffer_t) { - enum gtpc_version version; - bool piggyback; - bool tied_present; - enum gtpc_msg_type msg_type; - uint64_t teid; - uint64_t sequence; -} gtpc_header_t; + if (imsi_present) + + return 0; +} }; From 2088b3967b6604a4050273e3875a449c99c521a4 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 17 Nov 2017 11:59:22 +0000 Subject: [PATCH 073/172] Commenting out the initial GTP-C packing functions (for now). --- lib/include/srslte/asn1/gtpc.h | 3 ++- lib/include/srslte/asn1/gtpc_ies.h | 14 ++++++++++++++ lib/src/asn1/gtpc.cc | 4 ++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/include/srslte/asn1/gtpc.h b/lib/include/srslte/asn1/gtpc.h index 0b6d976f3..130ee525b 100644 --- a/lib/include/srslte/asn1/gtpc.h +++ b/lib/include/srslte/asn1/gtpc.h @@ -183,6 +183,7 @@ typedef struct gtpc_header * Ref: 3GPP TS 29.274 v10.14.0 Table 7.2.1-1 * ***************************************************************************/ +/* typedef struct gtpc_create_session_request { bool imsi_present; @@ -251,7 +252,7 @@ typedef struct gtpc_create_session_request uint8_t apco; // CO bool ext; // O } gtpc_create_session_request_t; - +*/ }; diff --git a/lib/include/srslte/asn1/gtpc_ies.h b/lib/include/srslte/asn1/gtpc_ies.h index be24a2da6..784dd6ac7 100644 --- a/lib/include/srslte/asn1/gtpc_ies.h +++ b/lib/include/srslte/asn1/gtpc_ies.h @@ -134,3 +134,17 @@ const uint8_t GTPC_IE_TYPE_APCO = 163; const uint8_t GTPC_IE_TYPE_CHANGE_TO_REPORT_FLAGS = 165; //168 TO 254 SPARE. FOR FUTURE USE. const uint8_t GTPC_IE_TYPE_PRIVATE_EXTENSION = 255; + + +/**************************************************************** + * + * GTP-C IMSI IE + * Ref: TS 29.274 v10.14.0 Table 8.3-1 + * + ****************************************************************/ +/* +The IMSI should be kept as a uint64_t. +The responsibility to convert from uint64_t to BCD coded is on +the pack_imsi_ie function +*/ +pack_imsi_ie(uint64_t imsi, **ptr); diff --git a/lib/src/asn1/gtpc.cc b/lib/src/asn1/gtpc.cc index 25d52c6d0..5ea29a349 100644 --- a/lib/src/asn1/gtpc.cc +++ b/lib/src/asn1/gtpc.cc @@ -29,7 +29,7 @@ namespace srslte{ - +/* int gtpc_pack_create_session_request(gtpc_create_session_request_t, srslte::byte_buffer_t) { @@ -37,5 +37,5 @@ gtpc_pack_create_session_request(gtpc_create_session_request_t, srslte::byte_buf return 0; } - +*/ }; From b6d0fcfdbe36b740874de8146a4929dd1e317139 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 17 Nov 2017 12:28:05 +0000 Subject: [PATCH 074/172] Renamed s-gw to sp-gw. --- srsepc/hdr/{sgw/sgw.h => spgw/spgw.h} | 24 ++++++++--------- srsepc/src/CMakeLists.txt | 2 +- srsepc/src/{sgw => spgw}/CMakeLists.txt | 0 srsepc/src/{sgw/sgw.cc => spgw/spgw.cc} | 34 ++++++++++++------------- 4 files changed, 30 insertions(+), 30 deletions(-) rename srsepc/hdr/{sgw/sgw.h => spgw/spgw.h} (82%) rename srsepc/src/{sgw => spgw}/CMakeLists.txt (100%) rename srsepc/src/{sgw/sgw.cc => spgw/spgw.cc} (73%) diff --git a/srsepc/hdr/sgw/sgw.h b/srsepc/hdr/spgw/spgw.h similarity index 82% rename from srsepc/hdr/sgw/sgw.h rename to srsepc/hdr/spgw/spgw.h index 85faa4c21..121daeee2 100644 --- a/srsepc/hdr/sgw/sgw.h +++ b/srsepc/hdr/spgw/spgw.h @@ -25,13 +25,13 @@ */ /****************************************************************************** - * File: sgw.h - * Description: Top-level S-GW class. Creates and links all + * File: spgw.h + * Description: Top-level SP-GW class. Creates and links all * interfaces and helpers. *****************************************************************************/ -#ifndef SGW_H -#define SGW_H +#ifndef SPGW_H +#define SPGW_H #include #include "srslte/common/log.h" @@ -44,30 +44,30 @@ namespace srsepc{ typedef struct { std::string gtpc_bind_addr; -} sgw_args_t; +} spgw_args_t; -class sgw: +class spgw: public thread { public: - static sgw* get_instance(void); + static spgw* get_instance(void); static void cleanup(void); - int init(sgw_args_t* args, srslte::log_filter *sgw_log); + int init(spgw_args_t* args, srslte::log_filter *spgw_log); void stop(); void run_thread(); private: - sgw(); - virtual ~sgw(); - static sgw *m_instance; + spgw(); + virtual ~spgw(); + static spgw *m_instance; bool m_running; srslte::byte_buffer_pool *m_pool; /*Logs*/ - srslte::log_filter *m_sgw_log; + srslte::log_filter *m_spgw_log; }; diff --git a/srsepc/src/CMakeLists.txt b/srsepc/src/CMakeLists.txt index 6ce5e44db..e6f4c2538 100644 --- a/srsepc/src/CMakeLists.txt +++ b/srsepc/src/CMakeLists.txt @@ -1,7 +1,7 @@ add_subdirectory(mme) add_subdirectory(hss) -add_subdirectory(sgw) +add_subdirectory(spgw) # Link libstdc++ and libgcc if(BUILD_STATIC) diff --git a/srsepc/src/sgw/CMakeLists.txt b/srsepc/src/spgw/CMakeLists.txt similarity index 100% rename from srsepc/src/sgw/CMakeLists.txt rename to srsepc/src/spgw/CMakeLists.txt diff --git a/srsepc/src/sgw/sgw.cc b/srsepc/src/spgw/spgw.cc similarity index 73% rename from srsepc/src/sgw/sgw.cc rename to srsepc/src/spgw/spgw.cc index 6293b57d5..3497afadb 100644 --- a/srsepc/src/sgw/sgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -26,39 +26,39 @@ #include #include -#include "sgw/sgw.h" +#include "spgw/spgw.h" namespace srsepc{ -sgw* sgw::m_instance = NULL; -boost::mutex sgw_instance_mutex; +spgw* spgw::m_instance = NULL; +boost::mutex spgw_instance_mutex; -sgw::sgw(): +spgw::spgw(): m_running(false) { m_pool = srslte::byte_buffer_pool::get_instance(); return; } -sgw::~sgw() +spgw::~spgw() { return; } -sgw* -sgw::get_instance(void) +spgw* +spgw::get_instance(void) { - boost::mutex::scoped_lock lock(sgw_instance_mutex); + boost::mutex::scoped_lock lock(spgw_instance_mutex); if(NULL == m_instance) { - m_instance = new sgw(); + m_instance = new spgw(); } return(m_instance); } void -sgw::cleanup(void) +spgw::cleanup(void) { - boost::mutex::scoped_lock lock(sgw_instance_mutex); + boost::mutex::scoped_lock lock(spgw_instance_mutex); if(NULL != m_instance) { delete m_instance; m_instance = NULL; @@ -66,17 +66,17 @@ sgw::cleanup(void) } int -sgw::init(sgw_args_t* args, srslte::log_filter *sgw_log) +spgw::init(spgw_args_t* args, srslte::log_filter *spgw_log) { - m_sgw_log = sgw_log; - m_sgw_log->info("S-GW Initialized.\n"); - m_sgw_log->console("S-GW Initialized.\n"); + m_spgw_log = spgw_log; + m_spgw_log->info("SP-GW Initialized.\n"); + m_spgw_log->console("SP-GW Initialized.\n"); return 0; } void -sgw::stop() +spgw::stop() { if(m_running) { @@ -88,7 +88,7 @@ sgw::stop() } void -sgw::run_thread() +spgw::run_thread() { //Mark the thread as running m_running=true; From eac3ee26c10d4b518c88d2d6b2caa85e7cbd8801 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 17 Nov 2017 16:04:42 +0000 Subject: [PATCH 075/172] Starting to add TUN if for SGi interface --- srsepc/hdr/spgw/spgw.h | 4 +++ srsepc/src/spgw/spgw.cc | 58 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/srsepc/hdr/spgw/spgw.h b/srsepc/hdr/spgw/spgw.h index 121daeee2..6d781cf61 100644 --- a/srsepc/hdr/spgw/spgw.h +++ b/srsepc/hdr/spgw/spgw.h @@ -63,9 +63,13 @@ private: virtual ~spgw(); static spgw *m_instance; + srslte::error_t init_sgi_if(); + bool m_running; srslte::byte_buffer_pool *m_pool; + int m_sgi_if; + int m_sgi_sock; /*Logs*/ srslte::log_filter *m_spgw_log; diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index 3497afadb..016188ec0 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -26,6 +26,12 @@ #include #include +#include +#include +#include +#include +#include +#include #include "spgw/spgw.h" namespace srsepc{ @@ -68,8 +74,11 @@ spgw::cleanup(void) int spgw::init(spgw_args_t* args, srslte::log_filter *spgw_log) { - + //Init log m_spgw_log = spgw_log; + + //Init Si interface + init_sgi_if(); m_spgw_log->info("SP-GW Initialized.\n"); m_spgw_log->console("SP-GW Initialized.\n"); return 0; @@ -99,4 +108,51 @@ spgw::run_thread() return; } +srslte::error_t +spgw::init_sgi_if() +{ + char dev[IFNAMSIZ] = "srs_spgw_sgi"; + struct ifreq ifr; + + // Construct the TUN device + m_sgi_if = open("/dev/net/tun", O_RDWR); + m_spgw_log->info("TUN file descriptor = %d\n", m_sgi_if); + if(m_sgi_if < 0) + { + m_spgw_log->debug("Failed to open TUN device: %s\n", strerror(errno)); + return(srslte::ERROR_CANT_START); + } + + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TUN | IFF_NO_PI; + strncpy(ifr.ifr_ifrn.ifrn_name, dev, IFNAMSIZ); + if(ioctl(m_sgi_if, TUNSETIFF, &ifr) < 0) + { + m_spgw_log->debug("Failed to set TUN device name: %s\n", strerror(errno)); + close(m_sgi_if); + return(srslte::ERROR_CANT_START); + } + + // Bring up the interface + m_sgi_sock = socket(AF_INET, SOCK_DGRAM, 0); + if(ioctl(m_sgi_sock, SIOCGIFFLAGS, &ifr) < 0) + { + m_spgw_log->debug("Failed to bring up socket: %s\n", strerror(errno)); + close(m_sgi_if); + return(srslte::ERROR_CANT_START); + } + ifr.ifr_flags |= IFF_UP | IFF_RUNNING; + if(ioctl(m_sgi_sock, SIOCSIFFLAGS, &ifr) < 0) + { + m_spgw_log->debug("Failed to set socket flags: %s\n", strerror(errno)); + close(m_sgi_if); + return(srslte::ERROR_CANT_START); + } + + //if_up = true; + + return(srslte::ERROR_NONE); + +} + } //namespace srsepc From f9b2c6434ab6dab49802b7520d35a2be8b164aa2 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 17 Nov 2017 18:01:06 +0000 Subject: [PATCH 076/172] Added TUN SGi interface to SP-GW. --- srsepc/hdr/spgw/spgw.h | 1 + srsepc/src/main.cc | 28 ++++++++++++++++++++++------ srsepc/src/spgw/spgw.cc | 20 ++++++++++++++++---- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/srsepc/hdr/spgw/spgw.h b/srsepc/hdr/spgw/spgw.h index 6d781cf61..ffd854b38 100644 --- a/srsepc/hdr/spgw/spgw.h +++ b/srsepc/hdr/spgw/spgw.h @@ -68,6 +68,7 @@ private: bool m_running; srslte::byte_buffer_pool *m_pool; + bool m_if_up; int m_sgi_if; int m_sgi_sock; /*Logs*/ diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index 1627a216c..eae1ab45b 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -29,6 +29,7 @@ #include "srslte/common/bcd_helpers.h" #include "mme/mme.h" #include "hss/hss.h" +#include "spgw/spgw.h" using namespace std; using namespace srsepc; @@ -49,9 +50,10 @@ typedef struct { typedef struct{ - mme_args_t mme_args; - hss_args_t hss_args; - log_args_t log_args; + mme_args_t mme_args; + hss_args_t hss_args; + spgw_args_t spgw_args; + log_args_t log_args; }all_args_t; /********************************************************************** @@ -197,6 +199,11 @@ main (int argc,char * argv[] ) hss_log.init("HSS ",logger); hss_log.set_level(srslte::LOG_LEVEL_DEBUG); hss_log.set_hex_limit(32); + + srslte::log_filter spgw_log; + spgw_log.init("SPGW",logger); + spgw_log.set_level(srslte::LOG_LEVEL_DEBUG); + spgw_log.set_hex_limit(32); mme *mme = mme::get_instance(); if (mme->init(&args.mme_args, &s1ap_log)) { @@ -209,15 +216,24 @@ main (int argc,char * argv[] ) cout << "Error initializing HSS" << endl; exit(1); } - + + spgw *spgw = spgw::get_instance(); + if (spgw->init(&args.spgw_args,&spgw_log)) { + cout << "Error initializing SP-GW" << endl; + exit(1); + } + mme->start(); + spgw->start(); while(running) { sleep(1); } mme->stop(); mme->cleanup(); - - cout << "--- exiting ---" << endl; + spgw->stop(); + spgw->cleanup(); + + cout << std::endl <<"--- exiting ---" << endl; return 0; } diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index 016188ec0..edceda337 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -40,7 +40,8 @@ spgw* spgw::m_instance = NULL; boost::mutex spgw_instance_mutex; spgw::spgw(): - m_running(false) + m_running(false), + m_if_up(false) { m_pool = srslte::byte_buffer_pool::get_instance(); return; @@ -92,6 +93,13 @@ spgw::stop() m_running = false; thread_cancel(); wait_thread_finish(); + + //Clean up interface + if(m_if_up) + { + close(m_sgi_if); + close(m_sgi_sock); + } } return; } @@ -114,6 +122,12 @@ spgw::init_sgi_if() char dev[IFNAMSIZ] = "srs_spgw_sgi"; struct ifreq ifr; + if(m_if_up) + { + return(srslte::ERROR_ALREADY_STARTED); + } + + // Construct the TUN device m_sgi_if = open("/dev/net/tun", O_RDWR); m_spgw_log->info("TUN file descriptor = %d\n", m_sgi_if); @@ -149,10 +163,8 @@ spgw::init_sgi_if() return(srslte::ERROR_CANT_START); } - //if_up = true; - + m_if_up = true; return(srslte::ERROR_NONE); - } } //namespace srsepc From 796fba6f5575ab3f32ada1fef95316d24690db26 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 20 Nov 2017 12:30:25 +0000 Subject: [PATCH 077/172] Adding socket for S1-U interface. --- srsepc/epc.conf.example | 3 +- srsepc/hdr/spgw/spgw.h | 13 ++++++-- srsepc/src/spgw/spgw.cc | 70 ++++++++++++++++++++++++++++++++++------- 3 files changed, 70 insertions(+), 16 deletions(-) diff --git a/srsepc/epc.conf.example b/srsepc/epc.conf.example index 16434ceee..e530a6dc4 100644 --- a/srsepc/epc.conf.example +++ b/srsepc/epc.conf.example @@ -21,5 +21,6 @@ mcc = 001 mnc = 01 mme_bind_addr = 127.0.0.0/24 - +[spgw] +s1u_bind_addr=127.0.0.1 diff --git a/srsepc/hdr/spgw/spgw.h b/srsepc/hdr/spgw/spgw.h index ffd854b38..1e4795019 100644 --- a/srsepc/hdr/spgw/spgw.h +++ b/srsepc/hdr/spgw/spgw.h @@ -42,8 +42,10 @@ namespace srsepc{ +const uint16_t GTPU_RX_PORT = 2152; + typedef struct { - std::string gtpc_bind_addr; + std::string gtpu_bind_addr; } spgw_args_t; @@ -63,14 +65,19 @@ private: virtual ~spgw(); static spgw *m_instance; - srslte::error_t init_sgi_if(); + srslte::error_t init_sgi_if(spgw_args_t *args); + srslte::error_t init_s1u(spgw_args_t *args); bool m_running; srslte::byte_buffer_pool *m_pool; - bool m_if_up; + bool m_sgi_up; int m_sgi_if; int m_sgi_sock; + + bool m_s1u_up; + int m_s1u; + /*Logs*/ srslte::log_filter *m_spgw_log; diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index edceda337..15820a12a 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -41,7 +41,8 @@ boost::mutex spgw_instance_mutex; spgw::spgw(): m_running(false), - m_if_up(false) + m_sgi_up(false), + m_s1u_up(false) { m_pool = srslte::byte_buffer_pool::get_instance(); return; @@ -75,11 +76,26 @@ spgw::cleanup(void) int spgw::init(spgw_args_t* args, srslte::log_filter *spgw_log) { + srslte::error_t err; + //Init log m_spgw_log = spgw_log; - //Init Si interface - init_sgi_if(); + //Init SGi interface + err = init_sgi_if(args); + if (err != srslte::ERROR_NONE) + { + m_spgw_log->console("Could not initialize the SGi interface.\n"); + return -1; + } + + //Init S1-U + err = init_s1u(args); + if (err != srslte::ERROR_NONE) + { + m_spgw_log->console("Could not initialize the S1-U interface.\n"); + return -1; + } m_spgw_log->info("SP-GW Initialized.\n"); m_spgw_log->console("SP-GW Initialized.\n"); return 0; @@ -94,12 +110,17 @@ spgw::stop() thread_cancel(); wait_thread_finish(); - //Clean up interface - if(m_if_up) + //Clean up SGi interface + if(m_sgi_up) { close(m_sgi_if); close(m_sgi_sock); } + //Clean up S1-U socket + if(m_s1u_up) + { + close(m_s1u); + } } return; } @@ -117,12 +138,12 @@ spgw::run_thread() } srslte::error_t -spgw::init_sgi_if() +spgw::init_sgi_if(spgw_args_t *args) { char dev[IFNAMSIZ] = "srs_spgw_sgi"; struct ifreq ifr; - if(m_if_up) + if(m_sgi_up) { return(srslte::ERROR_ALREADY_STARTED); } @@ -133,7 +154,7 @@ spgw::init_sgi_if() m_spgw_log->info("TUN file descriptor = %d\n", m_sgi_if); if(m_sgi_if < 0) { - m_spgw_log->debug("Failed to open TUN device: %s\n", strerror(errno)); + m_spgw_log->error("Failed to open TUN device: %s\n", strerror(errno)); return(srslte::ERROR_CANT_START); } @@ -142,7 +163,7 @@ spgw::init_sgi_if() strncpy(ifr.ifr_ifrn.ifrn_name, dev, IFNAMSIZ); if(ioctl(m_sgi_if, TUNSETIFF, &ifr) < 0) { - m_spgw_log->debug("Failed to set TUN device name: %s\n", strerror(errno)); + m_spgw_log->error("Failed to set TUN device name: %s\n", strerror(errno)); close(m_sgi_if); return(srslte::ERROR_CANT_START); } @@ -151,20 +172,45 @@ spgw::init_sgi_if() m_sgi_sock = socket(AF_INET, SOCK_DGRAM, 0); if(ioctl(m_sgi_sock, SIOCGIFFLAGS, &ifr) < 0) { - m_spgw_log->debug("Failed to bring up socket: %s\n", strerror(errno)); + m_spgw_log->error("Failed to bring up socket: %s\n", strerror(errno)); close(m_sgi_if); return(srslte::ERROR_CANT_START); } ifr.ifr_flags |= IFF_UP | IFF_RUNNING; if(ioctl(m_sgi_sock, SIOCSIFFLAGS, &ifr) < 0) { - m_spgw_log->debug("Failed to set socket flags: %s\n", strerror(errno)); + m_spgw_log->error("Failed to set socket flags: %s\n", strerror(errno)); close(m_sgi_if); return(srslte::ERROR_CANT_START); } - m_if_up = true; + m_sgi_up = true; return(srslte::ERROR_NONE); } +srslte::error_t +spgw::init_s1u(spgw_args_t *args) +{ + //Open S1-U socket + m_s1u = socket(AF_INET,SOCK_DGRAM,0); + if (m_s1u == -1) + { + m_spgw_log->error("Failed to open socket: %s\n", strerror(errno)); + return srslte::ERROR_CANT_START; + } + m_s1u_up = true; + + //Bind the socket + struct sockaddr_in servaddr; + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr=inet_addr(args->gtpu_bind_addr.c_str()); + servaddr.sin_port=htons(GTPU_RX_PORT); + + if (bind(m_s1u,(struct sockaddr *)&servaddr,sizeof(struct sockaddr_in))) { + m_spgw_log->error("Failed to bind socket: %s\n", strerror(errno)); + return srslte::ERROR_CANT_START; + } + return srslte::ERROR_NONE; +} + } //namespace srsepc From 606520d244540ff78d446660da093b2a0b44bb3d Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 20 Nov 2017 20:34:08 +0000 Subject: [PATCH 078/172] Added a TUN interface for the SGi and a socket to receive packets from the S1-U. Select is able choose the fd that needs to be read from. --- srsepc/epc.conf.example | 4 +-- srsepc/hdr/spgw/spgw.h | 1 + srsepc/src/main.cc | 6 ++++ srsepc/src/spgw/spgw.cc | 72 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 80 insertions(+), 3 deletions(-) diff --git a/srsepc/epc.conf.example b/srsepc/epc.conf.example index e530a6dc4..053915a1d 100644 --- a/srsepc/epc.conf.example +++ b/srsepc/epc.conf.example @@ -22,5 +22,5 @@ mnc = 01 mme_bind_addr = 127.0.0.0/24 [spgw] -s1u_bind_addr=127.0.0.1 - +gtpu_bind_addr=127.0.0.1 +sgi_if_addr=172.0.0.1 diff --git a/srsepc/hdr/spgw/spgw.h b/srsepc/hdr/spgw/spgw.h index 1e4795019..eb75ed57d 100644 --- a/srsepc/hdr/spgw/spgw.h +++ b/srsepc/hdr/spgw/spgw.h @@ -46,6 +46,7 @@ const uint16_t GTPU_RX_PORT = 2152; typedef struct { std::string gtpu_bind_addr; + std::string sgi_if_addr; } spgw_args_t; diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index eae1ab45b..b0a4b1432 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -71,6 +71,8 @@ parse_args(all_args_t *args, int argc, char* argv[]) { string mcc; string mnc; string mme_bind_addr; + string spgw_bind_addr; + string sgi_if_addr; // Command line only options bpo::options_description general("General options"); @@ -90,6 +92,8 @@ parse_args(all_args_t *args, int argc, char* argv[]) { ("mme.mcc", bpo::value(&mcc)->default_value("001"), "Mobile Country Code") ("mme.mnc", bpo::value(&mnc)->default_value("01"), "Mobile Network Code") ("mme.mme_bind_addr", bpo::value(&mme_bind_addr)->default_value("127.0.0.1"),"IP address of MME for S1 connnection") + ("spgw.gtpu_bind_addr", bpo::value(&spgw_bind_addr)->default_value("127.0.0.1"),"IP address of SP-GW for the S1-U connection") + ("spgw.sgi_if_addr", bpo::value(&sgi_if_addr)->default_value("176.16.0.1"),"IP address of TUN interface for the SGi connection") ; @@ -162,6 +166,8 @@ parse_args(all_args_t *args, int argc, char* argv[]) { } args->mme_args.s1ap_args.mme_bind_addr = mme_bind_addr; + args->spgw_args.gtpu_bind_addr = spgw_bind_addr; + args->spgw_args.sgi_if_addr = sgi_if_addr; return; } diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index 15820a12a..1d2169a9a 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -25,6 +25,7 @@ */ #include +#include #include #include #include @@ -39,6 +40,8 @@ namespace srsepc{ spgw* spgw::m_instance = NULL; boost::mutex spgw_instance_mutex; +const uint16_t SPGW_BUFFER_SIZE = 2500; + spgw::spgw(): m_running(false), m_sgi_up(false), @@ -130,10 +133,53 @@ spgw::run_thread() { //Mark the thread as running m_running=true; + srslte::byte_buffer_t *msg; + msg = m_pool->allocate(); + + struct sockaddr src_addr; + socklen_t addrlen; + + int sgi = m_sgi_if; + + fd_set set; + //struct timeval to; + int max_fd = std::max(m_s1u,sgi); while (m_running) { - sleep(1); + msg->reset(); + FD_ZERO(&set); + FD_SET(m_s1u, &set); + FD_SET(sgi, &set); + + m_spgw_log->info("Waiting for S1-U or SGi packets.\n"); + int n = select(max_fd+1, &set, NULL, NULL, NULL); + if (n == -1) + { + m_spgw_log->error("Error from select\n"); + } + else if (n) + { + m_spgw_log->info("Data is available now.\n"); + if (FD_ISSET(m_s1u, &set)) + { + msg->N_bytes = recvfrom(m_s1u, msg->msg, SRSLTE_MAX_BUFFER_SIZE_BYTES, 0, &src_addr, &addrlen ); + m_spgw_log->console("Received PDU from S1-U. Bytes %d\n", msg->N_bytes); + m_spgw_log->debug("Received PDU from S1-U. Bytes %d\n", msg->N_bytes); + } + if (FD_ISSET(m_sgi_if, &set)) + { + m_spgw_log->console("Received PDU from SGi\n"); + msg->N_bytes = read(sgi, msg->msg, SRSLTE_MAX_BUFFER_SIZE_BYTES); + m_spgw_log->console("Received PDU from SGi. Bytes %d\n", msg->N_bytes); + m_spgw_log->debug("Received PDU from SGi. Bytes %d\n", msg->N_bytes); + } + } + else + { + m_spgw_log->debug("No data from select.\n"); + } } + m_pool->deallocate(msg); return; } @@ -170,6 +216,7 @@ spgw::init_sgi_if(spgw_args_t *args) // Bring up the interface m_sgi_sock = socket(AF_INET, SOCK_DGRAM, 0); + if(ioctl(m_sgi_sock, SIOCGIFFLAGS, &ifr) < 0) { m_spgw_log->error("Failed to bring up socket: %s\n", strerror(errno)); @@ -184,6 +231,28 @@ spgw::init_sgi_if(spgw_args_t *args) return(srslte::ERROR_CANT_START); } + //Set IP of the interface + struct sockaddr_in *addr = (struct sockaddr_in*)&ifr.ifr_addr; + addr->sin_family = AF_INET; + addr->sin_addr.s_addr = inet_addr(args->sgi_if_addr.c_str()); + addr->sin_port = 0; + + if (ioctl(m_sgi_sock, SIOCSIFADDR, &ifr) < 0) { + m_spgw_log->error("Failed to set TUN interface IP. Address: %s, Error: %s\n", args->sgi_if_addr.c_str(), strerror(errno)); + close(m_sgi_if); + close(m_sgi_sock); + return srslte::ERROR_CANT_START; + } + + ifr.ifr_netmask.sa_family = AF_INET; + ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr("255.255.255.0"); + if (ioctl(m_sgi_sock, SIOCSIFNETMASK, &ifr) < 0) { + m_spgw_log->error("Failed to set TUN interface Netmask. Error: %s\n", strerror(errno)); + close(m_sgi_if); + close(m_sgi_sock); + return srslte::ERROR_CANT_START; + } + m_sgi_up = true; return(srslte::ERROR_NONE); } @@ -210,6 +279,7 @@ spgw::init_s1u(spgw_args_t *args) m_spgw_log->error("Failed to bind socket: %s\n", strerror(errno)); return srslte::ERROR_CANT_START; } + m_spgw_log->info("S1-U socket = %d\n", m_s1u); return srslte::ERROR_NONE; } From a8a370ec21573af390be37d44cbf1e1e99fb85b5 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 22 Nov 2017 11:52:37 +0000 Subject: [PATCH 079/172] Starting to add Create Session Request function --- lib/include/srslte/asn1/gtpc.h | 32 ++++++++++-- srsepc/hdr/mme/mme_gtpc.h | 48 +++++++++++++++++ srsepc/hdr/mme/s1ap.h | 16 +++--- srsepc/src/mme/mme_gtpc.cc | 96 ++++++++++++++++++++++++++++++++++ srsepc/src/mme/s1ap.cc | 15 ++++-- srsepc/src/spgw/spgw.cc | 8 +-- 6 files changed, 195 insertions(+), 20 deletions(-) create mode 100644 srsepc/hdr/mme/mme_gtpc.h create mode 100644 srsepc/src/mme/mme_gtpc.cc diff --git a/lib/include/srslte/asn1/gtpc.h b/lib/include/srslte/asn1/gtpc.h index 130ee525b..339a63d74 100644 --- a/lib/include/srslte/asn1/gtpc.h +++ b/lib/include/srslte/asn1/gtpc.h @@ -146,6 +146,20 @@ const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_STOP_RESPONSE = 236; //Other //240 - 255 For future use +/**************************************************************************** + * GTP-C v2 Message + * Ref: 3GPP TS 29.274 v10.14.0 + * + * This is the main structure to represent a GTP-C message. It is composed + * of one GTP-C header and one union of structures, which can hold + * all the possible GTP-C messages + ***************************************************************************/ +typedef struct gtpc_pdu +{ + struct gtpc_header; + union gtpc_msg_choice; +} gtpc_pdu_t; + /**************************************************************************** * GTP-C v2 Header * Ref: 3GPP TS 29.274 v10.14.0 Section 5 @@ -176,6 +190,16 @@ typedef struct gtpc_header uint64_t sequence; } gtpc_header_t; +/**************************************************************************** + * GTP-C v2 Header + * Ref: 3GPP TS 29.274 v10.14.0 Section 5 + * + * Union that hold the different structures for the possible message types. + ***************************************************************************/ +typedef union gtpc_msg_choice +{ + struct gtpc_create_session_request create_session_request; +}; /**************************************************************************** * @@ -186,9 +210,9 @@ typedef struct gtpc_header /* typedef struct gtpc_create_session_request { - bool imsi_present; + bool imsi_present; uint64_t imsi; // C - bool msidn_present; + bool msidn_present; uint64_t msisdn; // C bool mei_present; uint64_t mei; // C/CO @@ -196,11 +220,11 @@ typedef struct gtpc_create_session_request struct user_location_info_ uli; // C/CO bool serving_network_present; struct serving_network_ serving_network; // C/CO - + enum rat_type_ rat_type; // M bool indication_flags_present; struct indication_flags_ indication_flags; // C - + struct fteid_ sender_f_teid; // M bool pgw_addr_present; struct fteid_ pgw_addr; // C diff --git a/srsepc/hdr/mme/mme_gtpc.h b/srsepc/hdr/mme/mme_gtpc.h new file mode 100644 index 000000000..697046494 --- /dev/null +++ b/srsepc/hdr/mme/mme_gtpc.h @@ -0,0 +1,48 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ +#ifndef MME_GTPC_H +#define MME_GTPC_H + +namespace srsepc +{ + +class mme_gtpc +{ +public: + mme_gtpc(); + ~mme_gtpc(); + + static mme_gtpc* get_instance(void); + static void cleanup(void); + + void init(); + + void send_create_session_request(uint64_t imsi, struct create_session_response *cs_resp); + +}; + +} +#endif diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 23a01dac9..d51313c72 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -42,6 +42,7 @@ #include "mme/s1ap_common.h" #include "mme/s1ap_mngmt_proc.h" #include "mme/s1ap_nas_transport.h" +#include "mme/mme_gtpc.h" #include "hss/hss.h" namespace srsepc{ @@ -53,31 +54,29 @@ class s1ap public: s1ap(); virtual ~s1ap(); - int enb_listen(); + int enb_listen(); int init(s1ap_args_t s1ap_args, srslte::log_filter *s1ap_log); void stop(); int get_s1_mme(); - + void delete_enb_ctx(int32_t assoc_id); void delete_ues_in_enb(uint16_t enb_id); - bool handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb_sri); bool handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri); bool handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri); bool send_s1_setup_failure(struct sctp_sndrcvinfo *enb_sri); bool send_s1_setup_response(struct sctp_sndrcvinfo *enb_sri); - - bool handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, struct sctp_sndrcvinfo *enb_sri); + + bool handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, struct sctp_sndrcvinfo *enb_sri); bool handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, struct sctp_sndrcvinfo *enb_sri); bool handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri); bool handle_nas_authentication_response(srslte::byte_buffer_t *nas_buffer, srslte::byte_buffer_t *reply_buffer, ue_ctx_t *ue_ctx); bool handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx); - void print_enb_ctx_info(const enb_ctx_t &enb_ctx); private: @@ -95,9 +94,12 @@ private: std::map m_active_ues; std::map > m_enb_id_to_ue_ids; uint32_t m_next_mme_ue_s1ap_id; - + s1ap_mngmt_proc m_s1ap_mngmt_proc; s1ap_nas_transport m_s1ap_nas_transport; + + //FIXME the GTP-C should be moved to the MME class, the the packaging of GTP-C messages is done. + mme_gtpc *m_gtpc; }; diff --git a/srsepc/src/mme/mme_gtpc.cc b/srsepc/src/mme/mme_gtpc.cc new file mode 100644 index 000000000..0e0109cb2 --- /dev/null +++ b/srsepc/src/mme/mme_gtpc.cc @@ -0,0 +1,96 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include + +namespace srsepc{ + +mme_gtpc* mme_gtpc::m_instance = NULL; +boost::mutex mme_gtpc_instance_mutex; + +mme_gtpc::mme_gtpc(): +{ +} + +mme_gtpc::~mme_gtpc() +{ +} + +mme_gtpc* +mme_gtpc::get_instance(void) +{ + boost::mutex::scoped_lock lock(mme_gtpc_instance_mutex); + if(NULL == m_instance) { + m_instance = new mme_gtpc(); + } + return(m_instance); +} + +void +mme_gtpc::cleanup(void) +{ + boost::mutex::scoped_lock lock(mme_gtpc_instance_mutex); + if(NULL != m_instance) { + delete m_instance; + m_instance = NULL; + } +} + + +void +mme_gtpc::init() +{ + m_spgw = spgw::get_instance(); +} + +void +mme_gtpc::send_create_session_request(uint64_t imsi, struct create_session_response *cs_resp) +{ + uint64_t imsi; + struct gtpc_pdu cs_req; + + //Setup GTP-C Header. FIXME: Length, sequence and other fields need to be added. + cs_req.header.piggyback = false; + cs_req.header.teid_present = true; + cs_req.header.type = GTPC_MSG_TYPE_CREATE_SESSION_REQUEST; + cs_req.header.teid = 0; //Send create session request to the butler TEID + + //Setup GTP-C Create Session Request IEs + // Control TEID allocated \\ + cs_req.create_session_request.sender_f_teid.tied = get_new_ctrl_teid(); + cs_req.create_session_request.sender_f_teid.ip = htonl(m_mme_ip); + // APN \\ + memcpy(cs_req.create_session_request.apn, "internet", sizeof("internet")); + // RAT Type \\ + cs_req.create_session_request.rat_type = GTPC_RAT_TYPE::EUTRAN; + + //Save RX Control TEID + create_rx_control_teid(create_session_request.sender_f_tied); + + spgw->handle_create_session_request(&cs_req, cs_resp); + return; +} +} //namespace srsepc diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 16ebd19e1..a334d47dc 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -44,6 +44,7 @@ s1ap::~s1ap() int s1ap::init(s1ap_args_t s1ap_args, srslte::log_filter *s1ap_log) { + m_pool = srslte::byte_buffer_pool::get_instance(); m_s1ap_args = s1ap_args; srslte::s1ap_mccmnc_to_plmn(s1ap_args.mcc, s1ap_args.mnc, &m_plmn); @@ -51,8 +52,8 @@ s1ap::init(s1ap_args_t s1ap_args, srslte::log_filter *s1ap_log) m_s1ap_log = s1ap_log; m_s1ap_nas_transport.set_log(s1ap_log); - m_hss = hss::get_instance(); - m_pool = srslte::byte_buffer_pool::get_instance(); + m_hss = hss::get_instance(); + m_gtpc = mme_gtpc::get_instance(); m_s1mme = enb_listen(); @@ -445,7 +446,7 @@ s1ap::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, srslte: LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT auth_resp; bool ue_valid=true; - + //Get NAS authentication response LIBLTE_ERROR_ENUM err = liblte_mme_unpack_authentication_response_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &auth_resp); if(err != LIBLTE_SUCCESS){ @@ -469,7 +470,7 @@ s1ap::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, srslte: std::cout << std::hex <<(uint16_t)ue_ctx->xres[i]; } std::cout<console("UE Authentication Rejected. IMSI: %lu\n", ue_ctx->imsi); m_s1ap_log->warning("UE Authentication Rejected. IMSI: %lu\n", ue_ctx->imsi); //Send back Athentication Reject @@ -483,7 +484,11 @@ s1ap::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, srslte: //Send Security Mode Command m_s1ap_nas_transport.pack_security_mode_command(reply_msg, ue_ctx); - //m_gtpc->send_create_session_request(ue_ctx->imsi); + //FIXME The packging of GTP-C messages is not ready + //This means that GTP-U tunnels are created with function calls, as oposed to GTP-C. + //In future send_create_session_request will return void and the handle_create_session_response will be called from the GTP-C class itself. + struct gtpc_create_session_response *cs_resp = m_gtpc->send_create_session_request(ue_ctx->imsi); + m_gtpc->handle_create_session_response(cs_resp); } return true; } diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index 1d2169a9a..5f0a3d87f 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -83,7 +83,7 @@ spgw::init(spgw_args_t* args, srslte::log_filter *spgw_log) //Init log m_spgw_log = spgw_log; - + //Init SGi interface err = init_sgi_if(args); if (err != srslte::ERROR_NONE) @@ -112,7 +112,7 @@ spgw::stop() m_running = false; thread_cancel(); wait_thread_finish(); - + //Clean up SGi interface if(m_sgi_up) { @@ -135,7 +135,7 @@ spgw::run_thread() m_running=true; srslte::byte_buffer_t *msg; msg = m_pool->allocate(); - + struct sockaddr src_addr; socklen_t addrlen; @@ -150,7 +150,7 @@ spgw::run_thread() FD_ZERO(&set); FD_SET(m_s1u, &set); FD_SET(sgi, &set); - + m_spgw_log->info("Waiting for S1-U or SGi packets.\n"); int n = select(max_fd+1, &set, NULL, NULL, NULL); if (n == -1) From ccbeb9e1c5868e46512048165b41210b32916782 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 22 Nov 2017 14:41:59 +0000 Subject: [PATCH 080/172] Fixed a bunch of compilation errors. --- lib/include/srslte/asn1/gtpc.h | 122 +++++++++++++++++---------------- lib/src/asn1/gtpc.cc | 9 ++- srsepc/hdr/mme/mme_gtpc.h | 17 ++++- srsepc/src/mme/mme_gtpc.cc | 27 ++++---- 4 files changed, 97 insertions(+), 78 deletions(-) diff --git a/lib/include/srslte/asn1/gtpc.h b/lib/include/srslte/asn1/gtpc.h index 339a63d74..f41473bb0 100644 --- a/lib/include/srslte/asn1/gtpc.h +++ b/lib/include/srslte/asn1/gtpc.h @@ -146,68 +146,13 @@ const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_STOP_RESPONSE = 236; //Other //240 - 255 For future use -/**************************************************************************** - * GTP-C v2 Message - * Ref: 3GPP TS 29.274 v10.14.0 - * - * This is the main structure to represent a GTP-C message. It is composed - * of one GTP-C header and one union of structures, which can hold - * all the possible GTP-C messages - ***************************************************************************/ -typedef struct gtpc_pdu -{ - struct gtpc_header; - union gtpc_msg_choice; -} gtpc_pdu_t; - -/**************************************************************************** - * GTP-C v2 Header - * Ref: 3GPP TS 29.274 v10.14.0 Section 5 - * - * | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | - * - * 1 | Version | P | T | S | S | S | - * 2 | Message Type | - * 3 | Length (1st Octet) | - * 4 | Length (2nd Octet) | - * m | If T=1, TEID (1st Octet) | - * m+1 | If T=1, TEID (2nd Octet) | - * m+2 | If T=1, TEID (3st Octet) | - * m+3 | If T=1, TEID (4st Octet) | - * n | Sequence | - * n+1 | Sequence | - * n+2 | Sequence | - * n+3 | Spare | - ***************************************************************************/ - -typedef struct gtpc_header -{ - uint8_t version; - bool piggyback; - bool tied_present; - uint8_t msg_type; - uint64_t teid; - uint64_t sequence; -} gtpc_header_t; - -/**************************************************************************** - * GTP-C v2 Header - * Ref: 3GPP TS 29.274 v10.14.0 Section 5 - * - * Union that hold the different structures for the possible message types. - ***************************************************************************/ -typedef union gtpc_msg_choice -{ - struct gtpc_create_session_request create_session_request; -}; - /**************************************************************************** * * GTP-C v2 Create Session Request * Ref: 3GPP TS 29.274 v10.14.0 Table 7.2.1-1 * ***************************************************************************/ -/* + typedef struct gtpc_create_session_request { bool imsi_present; @@ -216,6 +161,7 @@ typedef struct gtpc_create_session_request uint64_t msisdn; // C bool mei_present; uint64_t mei; // C/CO + /* bool user_location_info_present; struct user_location_info_ uli; // C/CO bool serving_network_present; @@ -244,7 +190,7 @@ typedef struct gtpc_create_session_request uint8_t linked_eps_bearer_id; // C bool pco_present; uint8_t pco; // C - + struct bearer_context_ bearer_context_created; // M bool bearer_context_deleted_present; struct bearer_context_ bearer_context_deleted; // C @@ -275,8 +221,68 @@ typedef struct gtpc_create_session_request bool acpo_present; uint8_t apco; // CO bool ext; // O + */ } gtpc_create_session_request_t; -*/ + + +/**************************************************************************** + * GTP-C v2 Header + * Ref: 3GPP TS 29.274 v10.14.0 Section 5 + * + * | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | + * + * 1 | Version | P | T | S | S | S | + * 2 | Message Type | + * 3 | Length (1st Octet) | + * 4 | Length (2nd Octet) | + * m | If T=1, TEID (1st Octet) | + * m+1 | If T=1, TEID (2nd Octet) | + * m+2 | If T=1, TEID (3st Octet) | + * m+3 | If T=1, TEID (4st Octet) | + * n | Sequence | + * n+1 | Sequence | + * n+2 | Sequence | + * n+3 | Spare | + ***************************************************************************/ + + typedef struct gtpc_header + { + uint8_t version; + bool piggyback; + bool teid_present; + uint8_t type; + uint64_t teid; + uint64_t sequence; + } gtpc_header_t; + +/**************************************************************************** + * GTP-C v2 Payload + * Ref: 3GPP TS 29.274 v10.14.0 Section 5 + * + * Union that hold the different structures for the possible message types. + ***************************************************************************/ + +typedef union gtpc_msg_choice +{ + struct gtpc_create_session_request create_session_request; +} gtpc_msg_choice_t; + +/**************************************************************************** + * GTP-C v2 Message + * Ref: 3GPP TS 29.274 v10.14.0 + * + * This is the main structure to represent a GTP-C message. It is composed + * of one GTP-C header and one union of structures, which can hold + * all the possible GTP-C messages + ***************************************************************************/ + +typedef struct gtpc_pdu +{ + struct gtpc_header header; + union gtpc_msg_choice choice; +} gtpc_pdu_t; + + }; diff --git a/lib/src/asn1/gtpc.cc b/lib/src/asn1/gtpc.cc index 5ea29a349..d5c7320de 100644 --- a/lib/src/asn1/gtpc.cc +++ b/lib/src/asn1/gtpc.cc @@ -25,17 +25,16 @@ */ #include #include "srslte/asn1/gtpc.h" - +#include "srslte/common/common.h" namespace srslte{ -/* + int gtpc_pack_create_session_request(gtpc_create_session_request_t, srslte::byte_buffer_t) { - if (imsi_present) - + //FIXME return 0; } -*/ + }; diff --git a/srsepc/hdr/mme/mme_gtpc.h b/srsepc/hdr/mme/mme_gtpc.h index 697046494..a393cfe56 100644 --- a/srsepc/hdr/mme/mme_gtpc.h +++ b/srsepc/hdr/mme/mme_gtpc.h @@ -26,22 +26,33 @@ #ifndef MME_GTPC_H #define MME_GTPC_H +#include "srslte/common/buffer_pool.h" +#include +#include "spgw/spgw.h" + namespace srsepc { class mme_gtpc { public: - mme_gtpc(); - ~mme_gtpc(); static mme_gtpc* get_instance(void); static void cleanup(void); void init(); - void send_create_session_request(uint64_t imsi, struct create_session_response *cs_resp); +private: + + mme_gtpc(); + virtual ~mme_gtpc(); + static mme_gtpc *m_instance; + + srslte::byte_buffer_pool *m_pool; + + spgw* m_spgw; + in_addr_t m_mme_gtpc_ip; }; } diff --git a/srsepc/src/mme/mme_gtpc.cc b/srsepc/src/mme/mme_gtpc.cc index 0e0109cb2..413e4e50f 100644 --- a/srsepc/src/mme/mme_gtpc.cc +++ b/srsepc/src/mme/mme_gtpc.cc @@ -25,13 +25,15 @@ */ #include +#include "srslte/asn1/gtpc.h" +#include "mme/mme_gtpc.h" namespace srsepc{ mme_gtpc* mme_gtpc::m_instance = NULL; boost::mutex mme_gtpc_instance_mutex; -mme_gtpc::mme_gtpc(): +mme_gtpc::mme_gtpc() { } @@ -63,32 +65,33 @@ mme_gtpc::cleanup(void) void mme_gtpc::init() { + m_mme_gtpc_ip = inet_addr("127.0.0.1");//FIXME At the moment, the GTP-C messages are not sent over the wire. So this parameter is not used. m_spgw = spgw::get_instance(); } void mme_gtpc::send_create_session_request(uint64_t imsi, struct create_session_response *cs_resp) { - uint64_t imsi; - struct gtpc_pdu cs_req; + struct srslte::gtpc_pdu cs_req_pdu; + struct srslte::gtpc_create_session_request *cs_req = &cs_req_pdu.choice.create_session_request; //Setup GTP-C Header. FIXME: Length, sequence and other fields need to be added. - cs_req.header.piggyback = false; - cs_req.header.teid_present = true; - cs_req.header.type = GTPC_MSG_TYPE_CREATE_SESSION_REQUEST; - cs_req.header.teid = 0; //Send create session request to the butler TEID + cs_req_pdu.header.piggyback = false; + cs_req_pdu.header.teid_present = true; + cs_req_pdu.header.teid = 0; //Send create session request to the butler TEID + cs_req_pdu.header.type = srslte::GTPC_MSG_TYPE_CREATE_SESSION_REQUEST; //Setup GTP-C Create Session Request IEs // Control TEID allocated \\ - cs_req.create_session_request.sender_f_teid.tied = get_new_ctrl_teid(); - cs_req.create_session_request.sender_f_teid.ip = htonl(m_mme_ip); + cs_req->sender_f_teid.tied = get_new_ctrl_teid(); + cs_req->sender_f_teid.ip = m_mme_gtpc_ip; // APN \\ - memcpy(cs_req.create_session_request.apn, "internet", sizeof("internet")); + memcpy(cs_req->apn, "internet", sizeof("internet")); // RAT Type \\ - cs_req.create_session_request.rat_type = GTPC_RAT_TYPE::EUTRAN; + cs_req->rat_type = GTPC_RAT_TYPE::EUTRAN; //Save RX Control TEID - create_rx_control_teid(create_session_request.sender_f_tied); + create_rx_control_teid(cs_req->sender_f_tied); spgw->handle_create_session_request(&cs_req, cs_resp); return; From e754c6cbf512b281eab31f882301a857481ec5e8 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 23 Nov 2017 11:23:40 +0000 Subject: [PATCH 081/172] Fixed more compilation bugs. Bearer context IE still needs to be added. --- lib/include/srslte/asn1/gtpc.h | 195 +-------------- lib/include/srslte/asn1/gtpc_ies.h | 390 +++++++++++++++++++++-------- lib/include/srslte/asn1/gtpc_msg.h | 223 +++++++++++++++++ srsepc/src/mme/mme_gtpc.cc | 2 +- 4 files changed, 509 insertions(+), 301 deletions(-) create mode 100644 lib/include/srslte/asn1/gtpc_msg.h diff --git a/lib/include/srslte/asn1/gtpc.h b/lib/include/srslte/asn1/gtpc.h index f41473bb0..362765935 100644 --- a/lib/include/srslte/asn1/gtpc.h +++ b/lib/include/srslte/asn1/gtpc.h @@ -25,206 +25,13 @@ #define GTPC_V2_H #include - +#include "srslte/asn1/gtpc_msg.h" namespace srslte{ /*GTP-C Version*/ const uint8_t GTPC_V2 = 2; -/**************************************************************** - * - * GTP-C Message Types - * Ref: TS 29.274 v10.14.0 Table 6.1-1 - * - ****************************************************************/ -const uint8_t GTPC_MSG_TYPE_RESERVED = 0; -const uint8_t GTPC_MSG_TYPE_ECHO_REQUEST = 1; -const uint8_t GTPC_MSG_TYPE_ECHO_RESPONSE = 2; -const uint8_t GTPC_MSG_TYPE_VERSION_SUPPORT = 3; -//4-24 Reserved for S101 -//25-31 Reserved for Sv interface -//SGSN/MME/ePDG to PGW (S4/S11, S5/S8, S2b) -const uint8_t GTPC_MSG_TYPE_CREATE_SESSION_REQUEST = 32; -const uint8_t GTPC_MSG_TYPE_CREATE_SESSION_RESPONSE = 33; -const uint8_t GTPC_MSG_TYPE_DELETE_SESSION_REQUEST = 36; -const uint8_t GTPC_MSG_TYPE_DELETE_SESSION_RESPONSE = 37; -//SGSN/MME to PGW (S4/S11, S5/S8) -const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_REQUEST = 34; -const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_RESPONSE = 35; -const uint8_t GTPC_MSG_TYPE_CHANGE_NOTIFICATION_REQUEST = 38; -const uint8_t GTPC_MSG_TYPE_CHANGE_NOTIFICATION_RESPONSE = 39; -//40 - 63 for future use -const uint8_t GTPC_MSG_TYPE_RESUME_NOTIFICATION = 164; -const uint8_t GTPC_MSG_TYPE_RESUME_ACKNOWLEDGE = 165; -//Messages without explicit response -const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_COMMAND = 64; //(MME/SGSN/ePDG to PGW – S11/S4, S5/S8, S2b) -const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_FAILURE_INDICATION = 65; //(PGW to MME/SGSN/ePDG – S5/S8, S11/S4, S2b) -const uint8_t GTPC_MSG_TYPE_DELETE_BEARER_COMMAND = 66; //(MME/SGSN to PGW – S11/S4, S5/S8) -const uint8_t GTPC_MSG_TYPE_DELETE_BEARER_FAILURE_INDICATION = 67; //(PGW to MME/SGSN – S5/S8, S11/S4)) -const uint8_t GTPC_MSG_TYPE_BEARER_RESOURCE_COMMAND = 68; //(MME/SGSN to PGW – S11/S4, S5/S8) -const uint8_t GTPC_MSG_TYPE_BEARER_RESOURCE_FAILURE_INDICATION = 69; //(PGW to MME/SGSN – S5/S8, S11/S4) -const uint8_t GTPC_MSG_TYPE_DOWNLINK_DATA_NOTIFICATION_FAILURE_INDICATION = 70; //(SGSN/MME to SGW – S4/S11) -const uint8_t GTPC_MSG_TYPE_TRACE_SESSION_ACTIVATION = 71; //(MME/SGSN/ePDG to PGW – S11/S4, S5/S8, S2b) -const uint8_t GTPC_MSG_TYPE_TRACE_SESSION_DEACTIVATION = 72; //(MME/SGSN/ePDG to PGW – S11/S4, S5/S8, S2b) -const uint8_t GTPC_MSG_TYPE_STOP_PAGING_INDICATION = 73; //(SGW to MME/SGSN – S11/S4) -//74-94 For future use -//P-GW to SGSN/MME/ePDG -const uint8_t GTPC_MSG_TYPE_CREATE_BEARER_REQUEST = 95; -const uint8_t GTPC_MSG_TYPE_CREATE_BEARER_RESPONSE = 96; -const uint8_t GTPC_MSG_TYPE_UPDATE_BEARER_REQUEST = 97; -const uint8_t GTPC_MSG_TYPE_UPDATE_BEARER_RESPONSE = 98; -const uint8_t GTPC_MSG_TYPE_DELETE_BEARER_REQUEST = 99; -const uint8_t GTPC_MSG_TYPE_DELETE_BEARER_RESPONSE = 100; -//PGW to MME, MME to PGW, SGW to PGW, SGW to MME, PGW to ePDG, ePDG to PGW (S5/S8, S11, S2b) -const uint8_t GTPC_MSG_TYPE_DELETE_PDN_CONNECTION_SET_REQUEST = 101; -const uint8_t GTPC_MSG_TYPE_DELETE_PDN_CONNECTION_SET_RESPONSE = 102; -//103-127 For future use -//MME to MME, SGSN to MME, MME to SGSN, SGSN to SGSN (S3/S10/S16) -const uint8_t GTPC_MSG_TYPE_IDENTIFICATION_REQUEST = 128; -const uint8_t GTPC_MSG_TYPE_IDENTIFICATION_RESPONSE = 129; -const uint8_t GTPC_MSG_TYPE_CONTEXT_REQUEST = 130; -const uint8_t GTPC_MSG_TYPE_CONTEXT_RESPONSE = 131; -const uint8_t GTPC_MSG_TYPE_CONTEXT_ACKNOWLEDGE = 132; -const uint8_t GTPC_MSG_TYPE_FORWARD_RELOCATION_REQUEST = 133; -const uint8_t GTPC_MSG_TYPE_FORWARD_RELOCATION_RESPONSE = 134; -const uint8_t GTPC_MSG_TYPE_FORWARD_RELOCATION_COMPLETE_NOTIFICATION = 135; -const uint8_t GTPC_MSG_TYPE_FORWARD_RELOCATION_COMPLETE_ACKNOWLEDGE = 136; -const uint8_t GTPC_MSG_TYPE_FORWARD_ACCESS_CONTEXT_NOTIFICATION = 137; -const uint8_t GTPC_MSG_TYPE_FORWARD_ACCESS_CONTEXT_ACKNOWLEDGE = 138; -const uint8_t GTPC_MSG_TYPE_RELOCATION_CANCEL_REQUEST = 139; -const uint8_t GTPC_MSG_TYPE_RELOCATION_CANCEL_RESPONSE = 140; -const uint8_t GTPC_MSG_TYPE_CONFIGURATION_TRANSFER_TUNNEL = 141; -//142 - 148 For future use -const uint8_t GTPC_MSG_TYPE_RAN_INFORMATION_RELAY = 152; -//SGSN to MME, MME to SGSN (S3) -const uint8_t GTPC_MSG_TYPE_DETACH_NOTIFICATION = 149; -const uint8_t GTPC_MSG_TYPE_DETACH_ACKNOWLEDGE = 150; -const uint8_t GTPC_MSG_TYPE_CS_PAGING_INDICATION = 151; -const uint8_t GTPC_MSG_TYPE_ALERT_MME_NOTIFICATION = 153; -const uint8_t GTPC_MSG_TYPE_ALERT_MME_ACKNOWLEDGE = 154; -const uint8_t GTPC_MSG_TYPE_UE_ACTIVITY_NOTIFICATION = 155; -const uint8_t GTPC_MSG_TYPE_UE_ACTIVITY_ACKNOWLEDGE = 156; -//157 - 159 For future use -//GSN/MME to SGW, SGSN to MME (S4/S11/S3) SGSN to SGSN (S16), SGW to PGW (S5/S8) -const uint8_t GTPC_MSG_TYPE_SUSPEND_NOTIFICATION = 162; -const uint8_t GTPC_MSG_TYPE_SUSPEND_ACKNOWLEDGE = 163; -//SGSN/MME to SGW (S4/S11) const uint8_t GTPC_IE_TYPE_ -const uint8_t GTPC_MSG_TYPE_CREATE_FORWARDING_TUNNEL_REQUEST = 160; -const uint8_t GTPC_MSG_TYPE_CREATE_FORWARDING_TUNNEL_RESPONSE = 161; -const uint8_t GTPC_MSG_TYPE_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST = 166; -const uint8_t GTPC_MSG_TYPE_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE = 167; -const uint8_t GTPC_MSG_TYPE_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST = 168; -const uint8_t GTPC_MSG_TYPE_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE = 169; -const uint8_t GTPC_MSG_TYPE_RELEASE_ACCESS_BEARERS_REQUEST = 170; -const uint8_t GTPC_MSG_TYPE_RELEASE_ACCESS_BEARERS_RESPONSE = 171; -//172 - 175 For future use -//SGW to SGSN/MME (S4/S11) -const uint8_t GTPC_MSG_TYPE_DOWNLINK_DATA_NOTIFICATION = 176; -const uint8_t GTPC_MSG_TYPE_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE = 177; -const uint8_t GTPC_MSG_TYPE_PGW_RESTART_NOTIFICATION = 179; -const uint8_t GTPC_MSG_TYPE_PGW_RESTART_NOTIFICATION_ACKNOWLEDGE = 180; -//SGW to SGSN (S4) -//178 Reserved. Allocated in earlier version of the specification. -//181 -189 For future use -//SGW to PGW, PGW to SGW (S5/S8) -const uint8_t GTPC_MSG_TYPE_UPDATE_PDN_CONNECTION_SET_REQUEST = 200; -const uint8_t GTPC_MSG_TYPE_UPDATE_PDN_CONNECTION_SET_RESPONSE = 201; -//For future use -//MME to SGW (S11) -const uint8_t GTPC_MSG_TYPE_MODIFY_ACCESS_BEARERS_REQUEST = 211; -const uint8_t GTPC_MSG_TYPE_MODIFY_ACCESS_BEARERS_RESPONSE = 212; -//For future use -//MBMS GW to MME/SGSN (Sm/Sn) -const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_START_REQUEST = 231; -const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_START_RESPONSE = 232; -const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_UPDATE_REQUEST = 233; -const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_UPDATE_RESPONSE = 234; -const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_STOP_REQUEST = 235; -const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_STOP_RESPONSE = 236; -//For future use -//Other -//240 - 255 For future use - -/**************************************************************************** - * - * GTP-C v2 Create Session Request - * Ref: 3GPP TS 29.274 v10.14.0 Table 7.2.1-1 - * - ***************************************************************************/ - -typedef struct gtpc_create_session_request -{ - bool imsi_present; - uint64_t imsi; // C - bool msidn_present; - uint64_t msisdn; // C - bool mei_present; - uint64_t mei; // C/CO - /* - bool user_location_info_present; - struct user_location_info_ uli; // C/CO - bool serving_network_present; - struct serving_network_ serving_network; // C/CO - - enum rat_type_ rat_type; // M - bool indication_flags_present; - struct indication_flags_ indication_flags; // C - - struct fteid_ sender_f_teid; // M - bool pgw_addr_present; - struct fteid_ pgw_addr; // C - - uint64_t apn; // M - bool selection_mode_present; - enum selection_mode_ selection_mode; // C/CO - bool pdn_type_present; - enum pdn_type_ pdn_type; // C - bool pdn_addr_alloc_present; - struct pdn_addr_alloc_ pdn_addr_alloc; // C/CO - bool max_apn_restriction_present; - enum apn_restriction_ max_apn_restriction; // C - bool apn_ambr_present; - struct ambr_ apn_ambr; // C - bool linked_eps_bearer_id_present; - uint8_t linked_eps_bearer_id; // C - bool pco_present; - uint8_t pco; // C - - struct bearer_context_ bearer_context_created; // M - bool bearer_context_deleted_present; - struct bearer_context_ bearer_context_deleted; // C - bool trace_information_present; - struct trace_infromation_ trace_information; // C - bool recovery_present - uint8_t recovery; // C - bool mme_fq_csid_present; - struct fq_csid_ mme_fq_csid; // C - bool sgw_fq_csid_present; - struct fq_csid_ sgw_fq_csid; // C - bool epdg_fq_csid_present; - struct fq_csid_ epdg_fq_csid; // C - bool ue_time_zone_present; - struct ue_time_zone_ ue_time_zone; // CO - bool uci_present; - struct uci_ uci; // CO - bool charging_caracteristics_present; - enum charging_characteristics_ charging_caracteristics; // O - bool mme_ldn_present; - uint8_t mme_ldn[LDN_MAX_SIZE]; // O - bool sgw_ldn_present; - uint8_t sgw_ldn[LDN_MAX_SIZE]; // O - bool epgd_ldn_present; - uint8_t epdg_ldn[LDN_MAX_SIZE]; // O - bool signaling_priority_indication; - enum signalling_priority_indication_ spi; // CO - bool acpo_present; - uint8_t apco; // CO - bool ext; // O - */ -} gtpc_create_session_request_t; - - /**************************************************************************** * GTP-C v2 Header * Ref: 3GPP TS 29.274 v10.14.0 Section 5 diff --git a/lib/include/srslte/asn1/gtpc_ies.h b/lib/include/srslte/asn1/gtpc_ies.h index 784dd6ac7..e643b8f41 100644 --- a/lib/include/srslte/asn1/gtpc_ies.h +++ b/lib/include/srslte/asn1/gtpc_ies.h @@ -22,6 +22,13 @@ * */ +#ifndef GTPC_IES_H +#define GTPC_IES_H + + +#include "srslte/phy/io/netsource.h" +//#include +//#include /**************************************************************** * @@ -29,122 +36,293 @@ * Ref: TS 29.274 v10.14.0 Table 8.1-1 * ****************************************************************/ - -const uint8_t GTPC_IE_TYPE_RESERVED = 0; -const uint8_t GTPC_IE_TYPE_IMSI = 1; -const uint8_t GTPC_IE_TYPE_CAUSE = 2; -const uint8_t GTPC_IE_TYPE_RECOVERY = 3; +enum gtpc_ie_type +{ +//const uint8_t GTPC_IE_TYPE_RESERVED = 0; + GTPC_IE_TYPE_IMSI = 1, + GTPC_IE_TYPE_CAUSE = 2, + GTPC_IE_TYPE_RECOVERY = 3, //4 to 50 RESERVED_FOR_S101_INTERFACE -const uint8_t GTPC_IE_TYPE_STN_SR = 51 + GTPC_IE_TYPE_STN_SR = 51, //52 to 70 RESERVED_FOR_SV_INTERFACE -const uint8_t GTPC_IE_TYPE_APN = 71; -const uint8_t GTPC_IE_TYPE_AMBR = 72; -const uint8_t GTPC_IE_TYPE_EBI = 73; -const uint8_t GTPC_IE_TYPE_IP_ADDRESS = 74; -const uint8_t GTPC_IE_TYPE_MEI = 75; -const uint8_t GTPC_IE_TYPE_MSISDN = 76; -const uint8_t GTPC_IE_TYPE_INDICATION = 77; -const uint8_t GTPC_IE_TYPE_PCO = 78; -const uint8_t GTPC_IE_TYPE_PDN_ADDRESS_ALLOCATION = 79; -const uint8_t GTPC_IE_TYPE_BEARER_QOS = 80; -const uint8_t GTPC_IE_TYPE_FLOW_QOS = 81; -const uint8_t GTPC_IE_TYPE_RAT_TYPE = 82; -const uint8_t GTPC_IE_TYPE_SERVING_NETWORK = 83; -const uint8_t GTPC_IE_TYPE_BEARER_TFT = 84; -const uint8_t GTPC_IE_TYPE_TAD = 85; -const uint8_t GTPC_IE_TYPE_ULI = 86; -const uint8_t GTPC_IE_TYPE_F_TEID = 87; -const uint8_t GTPC_IE_TYPE_TMSI = 88; -const uint8_t GTPC_IE_TYPE_GLOBAL_CN_ID = 89; -const uint8_t GTPC_IE_TYPE_S103_PDN_DATA_FORWARDING_INFO = 90; -const uint8_t GTPC_IE_TYPE_S1_U_DATA_FORWARDING_INFO = 91; -const uint8_t GTPC_IE_TYPE_DELAY_VALUE = 92; -const uint8_t GTPC_IE_TYPE_BEARER_CONTEXT = 93; -const uint8_t GTPC_IE_TYPE_CHARGING_ID = 94; -const uint8_t GTPC_IE_TYPE_CHARGING_CHARACTERISTICS = 95; -const uint8_t GTPC_IE_TYPE_TRACE_INFORMATION = 96; -const uint8_t GTPC_IE_TYPE_BEARER_FLAGS = 97; -const uint8_t GTPC_IE_TYPE_RESERVED = 98; -const uint8_t GTPC_IE_TYPE_PDN_TYPE = 99; -const uint8_t GTPC_IE_TYPE_PROCEDURE_TRANSACTION_ID = 100; -const uint8_t GTPC_IE_TYPE_DRX_PARAMETER = 101; -const uint8_t GTPC_IE_TYPE_RESERVED = 102; -const uint8_t GTPC_IE_TYPE_MM_CONTEXT_GSM_KEY_AND_TRIPLETS = 103; -const uint8_t GTPC_IE_TYPE_MM_CONTEXT_UMTS_KEY_USED_CIPHER_AND_QUINTUPLETS = 104; -const uint8_t GTPC_IE_TYPE_MM_CONTEXT_GSM_KEY_USED_CIPHER_AND_QUINTUPLETS = 105; -const uint8_t GTPC_IE_TYPE_MM_CONTEXT_UMTS_KEY_AND_QUINTUPLETS = 106; -const uint8_t GTPC_IE_TYPE_MM_CONTEXT_EPS_SECURITY_CONTEXT_QUADRUPLETS_AND_QUINTUPLETS = 107; -const uint8_t GTPC_IE_TYPE_MM_CONTEXT_UMTS_KEY_QUADRUPLETS_AND_QUINTUPLETS = 108; -const uint8_t GTPC_IE_TYPE_PDN_CONNECTION = 109; -const uint8_t GTPC_IE_TYPE_PDU_NUMBERS = 110; -const uint8_t GTPC_IE_TYPE_P_TMSI = 111; -const uint8_t GTPC_IE_TYPE_P_TMSI_SIGNATURE = 112; -const uint8_t GTPC_IE_TYPE_HOP_COUNTER = 113; -const uint8_t GTPC_IE_TYPE_UE_TIME_ZONE = 114 -const uint8_t GTPC_IE_TYPE_TRACE_REFERENCE = 115; -const uint8_t GTPC_IE_TYPE_COMPLETE_REQUEST_MESSAGE = 116; -const uint8_t GTPC_IE_TYPE_GUTI = 117; -const uint8_t GTPC_IE_TYPE_F_CONTAINER = 118; -const uint8_t GTPC_IE_TYPE_F_CAUSE = 119; -const uint8_t GTPC_IE_TYPE_SELECTED_PLMN_ID = 120; -const uint8_t GTPC_IE_TYPE_TARGET_IDENTIFICATION = 121; -const uint8_t GTPC_IE_TYPE_RESERVED = 122; -const uint8_t GTPC_IE_TYPE_PACKET_FLOW_ID = 123; -const uint8_t GTPC_IE_TYPE_RAB_CONTEXT = 124; -const uint8_t GTPC_IE_TYPE_SOURCE_RNC_PDCP_CONTEXT_INFO = 125; -const uint8_t GTPC_IE_TYPE_UDP_SOURCE_PORT_NUMBER = 126; -const uint8_t GTPC_IE_TYPE_APN_RESTRICTION = 127; -const uint8_t GTPC_IE_TYPE_SELECTION_MODE = 128; -const uint8_t GTPC_IE_TYPE_SOURCE_IDENTIFICATION = 129; + GTPC_IE_TYPE_APN = 71, + GTPC_IE_TYPE_AMBR = 72, + GTPC_IE_TYPE_EBI = 73, + GTPC_IE_TYPE_IP_ADDRESS = 74, + GTPC_IE_TYPE_MEI = 75, + GTPC_IE_TYPE_MSISDN = 76, + GTPC_IE_TYPE_INDICATION = 77, + GTPC_IE_TYPE_PCO = 78, + GTPC_IE_TYPE_PDN_ADDRESS_ALLOCATION = 79, + GTPC_IE_TYPE_BEARER_QOS = 80, + GTPC_IE_TYPE_FLOW_QOS = 81, + GTPC_IE_TYPE_RAT_TYPE = 82, + GTPC_IE_TYPE_SERVING_NETWORK = 83, + GTPC_IE_TYPE_BEARER_TFT = 84, + GTPC_IE_TYPE_TAD = 85, + GTPC_IE_TYPE_ULI = 86, + GTPC_IE_TYPE_F_TEID = 87, + GTPC_IE_TYPE_TMSI = 88, + GTPC_IE_TYPE_GLOBAL_CN_ID = 89, + GTPC_IE_TYPE_S103_PDN_DATA_FORWARDING_INFO = 90, + GTPC_IE_TYPE_S1_U_DATA_FORWARDING_INFO = 91, + GTPC_IE_TYPE_DELAY_VALUE = 92, + GTPC_IE_TYPE_BEARER_CONTEXT = 93, + GTPC_IE_TYPE_CHARGING_ID = 94, + GTPC_IE_TYPE_CHARGING_CHARACTERISTICS = 95, + GTPC_IE_TYPE_TRACE_INFORMATION = 96, + GTPC_IE_TYPE_BEARER_FLAGS = 97, +//98 Reserved + GTPC_IE_TYPE_PDN_TYPE = 99, + GTPC_IE_TYPE_PROCEDURE_TRANSACTION_ID = 100, + GTPC_IE_TYPE_DRX_PARAMETER = 101, +//102 Reserved + GTPC_IE_TYPE_MM_CONTEXT_GSM_KEY_AND_TRIPLETS = 103, + GTPC_IE_TYPE_MM_CONTEXT_UMTS_KEY_USED_CIPHER_AND_QUINTUPLETS = 104, + GTPC_IE_TYPE_MM_CONTEXT_GSM_KEY_USED_CIPHER_AND_QUINTUPLETS = 105, + GTPC_IE_TYPE_MM_CONTEXT_UMTS_KEY_AND_QUINTUPLETS = 106, + GTPC_IE_TYPE_MM_CONTEXT_EPS_SECURITY_CONTEXT_QUADRUPLETS_AND_QUINTUPLETS = 107, + GTPC_IE_TYPE_MM_CONTEXT_UMTS_KEY_QUADRUPLETS_AND_QUINTUPLETS = 108, + GTPC_IE_TYPE_PDN_CONNECTION = 109, + GTPC_IE_TYPE_PDU_NUMBERS = 110, + GTPC_IE_TYPE_P_TMSI = 111, + GTPC_IE_TYPE_P_TMSI_SIGNATURE = 112, + GTPC_IE_TYPE_HOP_COUNTER = 113, + GTPC_IE_TYPE_UE_TIME_ZONE = 114, + GTPC_IE_TYPE_TRACE_REFERENCE = 115, + GTPC_IE_TYPE_COMPLETE_REQUEST_MESSAGE = 116, + GTPC_IE_TYPE_GUTI = 117, + GTPC_IE_TYPE_F_CONTAINER = 118, + GTPC_IE_TYPE_F_CAUSE = 119, + GTPC_IE_TYPE_SELECTED_PLMN_ID = 120, + GTPC_IE_TYPE_TARGET_IDENTIFICATION = 121, +//122 Reserved + GTPC_IE_TYPE_PACKET_FLOW_ID = 123, + GTPC_IE_TYPE_RAB_CONTEXT = 124, + GTPC_IE_TYPE_SOURCE_RNC_PDCP_CONTEXT_INFO = 125, + GTPC_IE_TYPE_UDP_SOURCE_PORT_NUMBER = 126, + GTPC_IE_TYPE_APN_RESTRICTION = 127, + GTPC_IE_TYPE_SELECTION_MODE = 128, + GTPC_IE_TYPE_SOURCE_IDENTIFICATION = 129, //130 RESERVED -const uint8_t GTPC_IE_TYPE_CHANGE_REPORTING_ACTION = 131; -const uint8_t GTPC_IE_TYPE_FQ_CSID = 132; -const uint8_t GTPC_IE_TYPE_CHANNEL_NEEDED = 133; -const uint8_t GTPC_IE_TYPE_EMLPP_PRIORITY = 134; -const uint8_t GTPC_IE_TYPE_NODE_TYPE = 135; -const uint8_t GTPC_IE_TYPE_FQDN = 136; -const uint8_t GTPC_IE_TYPE_TI = 137; -const uint8_t GTPC_IE_TYPE_MBMS_SESSION_DURATION = 138; -const uint8_t GTPC_IE_TYPE_MBMS_SERVICE_AREA = 139; -const uint8_t GTPC_IE_TYPE_MBMS_SESSION_IDENTIFIER = 140; -const uint8_t GTPC_IE_TYPE_MBMS_FLOW_IDENTIFIER = 141; -const uint8_t GTPC_IE_TYPE_MBMS_IP_MULTICAST_DISTRIBUTION = 142; -const uint8_t GTPC_IE_TYPE_MBMS_DISTRIBUTION_ACKNOWLEDGE = 143; -const uint8_t GTPC_IE_TYPE_RFSP_INDEX = 144; -const uint8_t GTPC_IE_TYPE_UCI = 145; -const uint8_t GTPC_IE_TYPE_CSG_INFORMATION_REPORTING_ACTION = 146; -const uint8_t GTPC_IE_TYPE_CSG_ID = 147; -const uint8_t GTPC_IE_TYPE_CMI = 148; -const uint8_t GTPC_IE_TYPE_SERVICE_INDICATOR = 149; -const uint8_t GTPC_IE_TYPE_DETACH_TYPE = 150; -const uint8_t GTPC_IE_TYPE_LDN = 151; -const uint8_t GTPC_IE_TYPE_NODE_FEATURES = 152; -const uint8_t GTPC_IE_TYPE_MBMS_TIME_TO_DATA_TRANSFER = 153; -const uint8_t GTPC_IE_TYPE_THROTTLING =154; -const uint8_t GTPC_IE_TYPE_ARP = 155; -const uint8_t GTPC_IE_TYPE_EPC_TIMER = 156; -const uint8_t GTPC_IE_TYPE_SIGNALLING_PRIORITY_INDICATION = 157; -const uint8_t GTPC_IE_TYPE_TMGI = 158; -const uint8_t GTPC_IE_TYPE_ADDITIONAL_MM_CONTEXT_FOR_SRVCC = 159; -const uint8_t GTPC_IE_TYPE_ADDITIONAL_FLAGS_FOR_SRVCC = 160; + GTPC_IE_TYPE_CHANGE_REPORTING_ACTION = 131, + GTPC_IE_TYPE_FQ_CSID = 132, + GTPC_IE_TYPE_CHANNEL_NEEDED = 133, + GTPC_IE_TYPE_EMLPP_PRIORITY = 134, + GTPC_IE_TYPE_NODE_TYPE = 135, + GTPC_IE_TYPE_FQDN = 136, + GTPC_IE_TYPE_TI = 137, + GTPC_IE_TYPE_MBMS_SESSION_DURATION = 138, + GTPC_IE_TYPE_MBMS_SERVICE_AREA = 139, + GTPC_IE_TYPE_MBMS_SESSION_IDENTIFIER = 140, + GTPC_IE_TYPE_MBMS_FLOW_IDENTIFIER = 141, + GTPC_IE_TYPE_MBMS_IP_MULTICAST_DISTRIBUTION = 142, + GTPC_IE_TYPE_MBMS_DISTRIBUTION_ACKNOWLEDGE = 143, + GTPC_IE_TYPE_RFSP_INDEX = 144, + GTPC_IE_TYPE_UCI = 145, + GTPC_IE_TYPE_CSG_INFORMATION_REPORTING_ACTION = 146, + GTPC_IE_TYPE_CSG_ID = 147, + GTPC_IE_TYPE_CMI = 148, + GTPC_IE_TYPE_SERVICE_INDICATOR = 149, + GTPC_IE_TYPE_DETACH_TYPE = 150, + GTPC_IE_TYPE_LDN = 151, + GTPC_IE_TYPE_NODE_FEATURES = 152, + GTPC_IE_TYPE_MBMS_TIME_TO_DATA_TRANSFER = 153, + GTPC_IE_TYPE_THROTTLING =154, + GTPC_IE_TYPE_ARP = 155, + GTPC_IE_TYPE_EPC_TIMER = 156, + GTPC_IE_TYPE_SIGNALLING_PRIORITY_INDICATION = 157, + GTPC_IE_TYPE_TMGI = 158, + GTPC_IE_TYPE_ADDITIONAL_MM_CONTEXT_FOR_SRVCC = 159, + GTPC_IE_TYPE_ADDITIONAL_FLAGS_FOR_SRVCC = 160, //161 RESERVED -const uint8_t GTPC_IE_TYPE_MDT_CONFIGURATION = 162; -const uint8_t GTPC_IE_TYPE_APCO = 163; + GTPC_IE_TYPE_MDT_CONFIGURATION = 162, + GTPC_IE_TYPE_APCO = 163, //164 RESERVED -const uint8_t GTPC_IE_TYPE_CHANGE_TO_REPORT_FLAGS = 165; + GTPC_IE_TYPE_CHANGE_TO_REPORT_FLAGS = 165, //168 TO 254 SPARE. FOR FUTURE USE. -const uint8_t GTPC_IE_TYPE_PRIVATE_EXTENSION = 255; - + GTPC_IE_TYPE_PRIVATE_EXTENSION = 255 +}; /**************************************************************** * * GTP-C IMSI IE - * Ref: TS 29.274 v10.14.0 Table 8.3-1 + * Ref: TS 29.274 v10.14.0 Figure 8.3-1 * ****************************************************************/ /* -The IMSI should be kept as a uint64_t. -The responsibility to convert from uint64_t to BCD coded is on -the pack_imsi_ie function -*/ -pack_imsi_ie(uint64_t imsi, **ptr); + * The IMSI should be kept as an uint64_t. + * The responsibility to convert from uint64_t to BCD coded is on + * the pack_imsi_ie function + */ + +/**************************************************************************** + * + * GTP-C Cause IE + * Ref: 3GPP TS 29.274 v10.14.0 Figure 8.4-1 and Table 8.4-1 + * + ***************************************************************************/ +enum gtpc_cause_value +{ + //Reserved + LOCAL_DETACH = 2, + COMPLETE_DETACH = 3, + RAT_CHANGED_FROM_3GPP_TO_NON_3GPP = 4, + ISR_DEACTIVATION = 5, + ERROR_INDICATION_RECEIVED_FROM_RNC_ENODEB_S4_SGSN = 6, + IMSI_DETACH_ONLY = 7, + REACTIVATION_REQUESTED = 8, + PDN_RECONNECTION_TO_THIS_APN_DISALLOWED = 9, + ACCESS_CHANGED_FROM_NON_3GPP_TO_3GPP = 10, + PDN_CONNECTION_INACTIVITY_TIMER_EXPIRES = 11 + //Spare. This value range shall be used by Cause values in an initial/request message. + +}; + +struct gtpc_cause_ie +{ + enum gtpc_cause_value cause_value; + bool pce; + bool bce; + bool cs; + enum gtpc_ie_type offending_ie_type; + uint16_t length_of_offending_ie; + uint8_t offending_ie_instance; +}; + +/**************************************************************************** + * + * GTP-C Recovery IE + * Ref: 3GPP TS 29.274 v10.14.0 Figure 8.5-1 + * + ***************************************************************************/ +/* + * The Recovery (Restart Counter) IE should be kept as an uint8_t. + */ + +/**************************************************************************** + * + * GTP-C Access Point Name IE + * Ref: 3GPP TS 29.274 v10.14.0 Figure 8.6-1 + * + ***************************************************************************/ +/* + * APN IE should be kept as an null terminated string. + * This string will be kept in a char[MAX_APN_LENGTH] buffer. + */ +#define MAX_APN_LENGTH 1024 + +/**************************************************************************** + * + * GTP-C Aggregate Maximum bit-rate IE + * Ref: 3GPP TS 29.274 v10.14.0 Table 8.7-1 + * + ***************************************************************************/ +struct gtpc_ambr_ie +{ + uint32_t apn_ambr_uplink; + uint32_t apn_ambr_downlink; +}; + +/**************************************************************************** + * + * GTP-C EPS Bearer ID address IE + * Ref: 3GPP TS 29.274 v10.14.0 Figure 8.8-1 + * + ***************************************************************************/ +/* + * The EPS Bearer ID (EBI) IE should be kept as an uint8_t. + */ + +/**************************************************************************** + * + * GTP-C IP address IE + * Ref: 3GPP TS 29.274 v10.14.0 Figure 8.9-1 + * + ***************************************************************************/ +/* + * IP addresses should the sockaddr_storage struct, which can hold IPv4 + * and IPv6 addresses. + */ + +//TODO +//TODO IEs between 8.10 and 8.17 missing +//TODO + +/**************************************************************************** + * + * GTP-C RAT Type IE + * Ref: 3GPP TS 29.274 v10.14.0 Figure 8.17-1 + * + ***************************************************************************/ + +enum gtpc_rat_type +{ + UTRAN = 1, + GERAN, + WLAN, + GAN, + HSPA_EVOLUTION, + EUTRAN, + Virtual +}; + +//TODO +//TODO IEs between 8.17 and 8.22 missing +//TODO + +/**************************************************************************** + * + * GTP-C Fully Qualified Tunnel End-point Identifier (F-TEID) IE + * Ref: 3GPP TS 29.274 v10.14.0 Figure 8.22-1 + * + ***************************************************************************/ +enum gtpc_interface_type +{ + S1_U_ENODEB_GTP_U_INTERFACE, + S1_U_SGW_GTP_U_INTERFACE, + S12_RNC_GTP_U_INTERFACE, + S12_SGW_GTP_U_INTERFACE, + S5_S8_SGW_GTP_U_INTERFACE, + S5_S8_PGW_GTP_U_INTERFACE, + S5_S8_SGW_GTP_C_INTERFACE, + S5_S8_PGW_GTP_C_INTERFACE, + S5_S8_SGW_PMIPV6_INTERFACE, //(the 32 bit GRE key is encoded in 32 bit TEID field and since alternate CoA is not used the control plane and user plane addresses are the same for PMIPv6) + S5_S8_PGW_PMIPV6_INTERFACE, //(the 32 bit GRE key is encoded in 32 bit TEID field and the control plane and user plane addresses are the same for PMIPv6) + S11_MME_GTP_C_INTERFACE, + S11_S4_SGW_GTP_C_INTERFACE, + S10_MME_GTP_C_INTERFACE, + S3_MME_GTP_C_INTERFACE, + S3_SGSN_GTP_C_INTERFACE, + S4_SGSN_GTP_U_INTERFACE, + S4_SGW_GTP_U_INTERFACE, + S4_SGSN_GTP_C_INTERFACE, + S16_SGSN_GTP_C_INTERFACE, + ENODEB_GTP_U_INTERFACE_FOR_DL_DATA_FORWARDING, + ENODEB_GTP_U_INTERFACE_FOR_UL_DATA_FORWARDING, + RNC_GTP_U_INTERFACE_FOR_DATA_FORWARDING, + SGSN_GTP_U_INTERFACE_FOR_DATA_FORWARDING, + SGW_GTP_U_INTERFACE_FOR_DL_DATA_FORWARDING, + SM_MBMS_GW_GTP_C_INTERFACE, + SN_MBMS_GW_GTP_C_INTERFACE, + SM_MME_GTP_C_INTERFACE, + SN_SGSN_GTP_C_INTERFACE, + SGW_GTP_U_INTERFACE_FOR_UL_DATA_FORWARDING, + SN_SGSN_GTP_U_INTERFACE, + S2B_EPDG_GTP_C_INTERFACE, + S2B_U_EPDG_GTP_U_INTERFACE, + S2B_PGW_GTP_C_INTERFACE, + S2B_U_PGW_GTP_U_INTERFACE +}; + +struct gtpc_f_teid_ie +{ + bool v4_present; + bool v6_present; + enum gtpc_interface_type interface_type; + uint32_t teid; + struct in_addr ipv4; + struct in6_addr ipv6; +}; + +#endif //GTPC_IES_H diff --git a/lib/include/srslte/asn1/gtpc_msg.h b/lib/include/srslte/asn1/gtpc_msg.h new file mode 100644 index 000000000..ccb2c7ae4 --- /dev/null +++ b/lib/include/srslte/asn1/gtpc_msg.h @@ -0,0 +1,223 @@ +/* \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsUE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsUE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ +#ifndef GTPC_V2_MSG_H +#define GTPC_V2_MSG_H + +#include "srslte/asn1/gtpc_ies.h" + +namespace srslte{ + +/**************************************************************** + * + * GTP-C Message Types + * Ref: TS 29.274 v10.14.0 Table 6.1-1 + * + ****************************************************************/ +const uint8_t GTPC_MSG_TYPE_RESERVED = 0; +const uint8_t GTPC_MSG_TYPE_ECHO_REQUEST = 1; +const uint8_t GTPC_MSG_TYPE_ECHO_RESPONSE = 2; +const uint8_t GTPC_MSG_TYPE_VERSION_SUPPORT = 3; +//4-24 Reserved for S101 +//25-31 Reserved for Sv interface +//SGSN/MME/ePDG to PGW (S4/S11, S5/S8, S2b) +const uint8_t GTPC_MSG_TYPE_CREATE_SESSION_REQUEST = 32; +const uint8_t GTPC_MSG_TYPE_CREATE_SESSION_RESPONSE = 33; +const uint8_t GTPC_MSG_TYPE_DELETE_SESSION_REQUEST = 36; +const uint8_t GTPC_MSG_TYPE_DELETE_SESSION_RESPONSE = 37; +//SGSN/MME to PGW (S4/S11, S5/S8) +const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_REQUEST = 34; +const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_RESPONSE = 35; +const uint8_t GTPC_MSG_TYPE_CHANGE_NOTIFICATION_REQUEST = 38; +const uint8_t GTPC_MSG_TYPE_CHANGE_NOTIFICATION_RESPONSE = 39; +//40 - 63 for future use +const uint8_t GTPC_MSG_TYPE_RESUME_NOTIFICATION = 164; +const uint8_t GTPC_MSG_TYPE_RESUME_ACKNOWLEDGE = 165; +//Messages without explicit response +const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_COMMAND = 64; //(MME/SGSN/ePDG to PGW – S11/S4, S5/S8, S2b) +const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_FAILURE_INDICATION = 65; //(PGW to MME/SGSN/ePDG – S5/S8, S11/S4, S2b) +const uint8_t GTPC_MSG_TYPE_DELETE_BEARER_COMMAND = 66; //(MME/SGSN to PGW – S11/S4, S5/S8) +const uint8_t GTPC_MSG_TYPE_DELETE_BEARER_FAILURE_INDICATION = 67; //(PGW to MME/SGSN – S5/S8, S11/S4)) +const uint8_t GTPC_MSG_TYPE_BEARER_RESOURCE_COMMAND = 68; //(MME/SGSN to PGW – S11/S4, S5/S8) +const uint8_t GTPC_MSG_TYPE_BEARER_RESOURCE_FAILURE_INDICATION = 69; //(PGW to MME/SGSN – S5/S8, S11/S4) +const uint8_t GTPC_MSG_TYPE_DOWNLINK_DATA_NOTIFICATION_FAILURE_INDICATION = 70; //(SGSN/MME to SGW – S4/S11) +const uint8_t GTPC_MSG_TYPE_TRACE_SESSION_ACTIVATION = 71; //(MME/SGSN/ePDG to PGW – S11/S4, S5/S8, S2b) +const uint8_t GTPC_MSG_TYPE_TRACE_SESSION_DEACTIVATION = 72; //(MME/SGSN/ePDG to PGW – S11/S4, S5/S8, S2b) +const uint8_t GTPC_MSG_TYPE_STOP_PAGING_INDICATION = 73; //(SGW to MME/SGSN – S11/S4) +//74-94 For future use +//P-GW to SGSN/MME/ePDG +const uint8_t GTPC_MSG_TYPE_CREATE_BEARER_REQUEST = 95; +const uint8_t GTPC_MSG_TYPE_CREATE_BEARER_RESPONSE = 96; +const uint8_t GTPC_MSG_TYPE_UPDATE_BEARER_REQUEST = 97; +const uint8_t GTPC_MSG_TYPE_UPDATE_BEARER_RESPONSE = 98; +const uint8_t GTPC_MSG_TYPE_DELETE_BEARER_REQUEST = 99; +const uint8_t GTPC_MSG_TYPE_DELETE_BEARER_RESPONSE = 100; +//PGW to MME, MME to PGW, SGW to PGW, SGW to MME, PGW to ePDG, ePDG to PGW (S5/S8, S11, S2b) +const uint8_t GTPC_MSG_TYPE_DELETE_PDN_CONNECTION_SET_REQUEST = 101; +const uint8_t GTPC_MSG_TYPE_DELETE_PDN_CONNECTION_SET_RESPONSE = 102; +//103-127 For future use +//MME to MME, SGSN to MME, MME to SGSN, SGSN to SGSN (S3/S10/S16) +const uint8_t GTPC_MSG_TYPE_IDENTIFICATION_REQUEST = 128; +const uint8_t GTPC_MSG_TYPE_IDENTIFICATION_RESPONSE = 129; +const uint8_t GTPC_MSG_TYPE_CONTEXT_REQUEST = 130; +const uint8_t GTPC_MSG_TYPE_CONTEXT_RESPONSE = 131; +const uint8_t GTPC_MSG_TYPE_CONTEXT_ACKNOWLEDGE = 132; +const uint8_t GTPC_MSG_TYPE_FORWARD_RELOCATION_REQUEST = 133; +const uint8_t GTPC_MSG_TYPE_FORWARD_RELOCATION_RESPONSE = 134; +const uint8_t GTPC_MSG_TYPE_FORWARD_RELOCATION_COMPLETE_NOTIFICATION = 135; +const uint8_t GTPC_MSG_TYPE_FORWARD_RELOCATION_COMPLETE_ACKNOWLEDGE = 136; +const uint8_t GTPC_MSG_TYPE_FORWARD_ACCESS_CONTEXT_NOTIFICATION = 137; +const uint8_t GTPC_MSG_TYPE_FORWARD_ACCESS_CONTEXT_ACKNOWLEDGE = 138; +const uint8_t GTPC_MSG_TYPE_RELOCATION_CANCEL_REQUEST = 139; +const uint8_t GTPC_MSG_TYPE_RELOCATION_CANCEL_RESPONSE = 140; +const uint8_t GTPC_MSG_TYPE_CONFIGURATION_TRANSFER_TUNNEL = 141; +//142 - 148 For future use +const uint8_t GTPC_MSG_TYPE_RAN_INFORMATION_RELAY = 152; +//SGSN to MME, MME to SGSN (S3) +const uint8_t GTPC_MSG_TYPE_DETACH_NOTIFICATION = 149; +const uint8_t GTPC_MSG_TYPE_DETACH_ACKNOWLEDGE = 150; +const uint8_t GTPC_MSG_TYPE_CS_PAGING_INDICATION = 151; +const uint8_t GTPC_MSG_TYPE_ALERT_MME_NOTIFICATION = 153; +const uint8_t GTPC_MSG_TYPE_ALERT_MME_ACKNOWLEDGE = 154; +const uint8_t GTPC_MSG_TYPE_UE_ACTIVITY_NOTIFICATION = 155; +const uint8_t GTPC_MSG_TYPE_UE_ACTIVITY_ACKNOWLEDGE = 156; +//157 - 159 For future use +//GSN/MME to SGW, SGSN to MME (S4/S11/S3) SGSN to SGSN (S16), SGW to PGW (S5/S8) +const uint8_t GTPC_MSG_TYPE_SUSPEND_NOTIFICATION = 162; +const uint8_t GTPC_MSG_TYPE_SUSPEND_ACKNOWLEDGE = 163; +//SGSN/MME to SGW (S4/S11) const uint8_t GTPC_IE_TYPE_ +const uint8_t GTPC_MSG_TYPE_CREATE_FORWARDING_TUNNEL_REQUEST = 160; +const uint8_t GTPC_MSG_TYPE_CREATE_FORWARDING_TUNNEL_RESPONSE = 161; +const uint8_t GTPC_MSG_TYPE_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST = 166; +const uint8_t GTPC_MSG_TYPE_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE = 167; +const uint8_t GTPC_MSG_TYPE_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST = 168; +const uint8_t GTPC_MSG_TYPE_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE = 169; +const uint8_t GTPC_MSG_TYPE_RELEASE_ACCESS_BEARERS_REQUEST = 170; +const uint8_t GTPC_MSG_TYPE_RELEASE_ACCESS_BEARERS_RESPONSE = 171; +//172 - 175 For future use +//SGW to SGSN/MME (S4/S11) +const uint8_t GTPC_MSG_TYPE_DOWNLINK_DATA_NOTIFICATION = 176; +const uint8_t GTPC_MSG_TYPE_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE = 177; +const uint8_t GTPC_MSG_TYPE_PGW_RESTART_NOTIFICATION = 179; +const uint8_t GTPC_MSG_TYPE_PGW_RESTART_NOTIFICATION_ACKNOWLEDGE = 180; +//SGW to SGSN (S4) +//178 Reserved. Allocated in earlier version of the specification. +//181 -189 For future use +//SGW to PGW, PGW to SGW (S5/S8) +const uint8_t GTPC_MSG_TYPE_UPDATE_PDN_CONNECTION_SET_REQUEST = 200; +const uint8_t GTPC_MSG_TYPE_UPDATE_PDN_CONNECTION_SET_RESPONSE = 201; +//For future use +//MME to SGW (S11) +const uint8_t GTPC_MSG_TYPE_MODIFY_ACCESS_BEARERS_REQUEST = 211; +const uint8_t GTPC_MSG_TYPE_MODIFY_ACCESS_BEARERS_RESPONSE = 212; +//For future use +//MBMS GW to MME/SGSN (Sm/Sn) +const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_START_REQUEST = 231; +const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_START_RESPONSE = 232; +const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_UPDATE_REQUEST = 233; +const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_UPDATE_RESPONSE = 234; +const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_STOP_REQUEST = 235; +const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_STOP_RESPONSE = 236; +//For future use +//Other +//240 - 255 For future use + +/**************************************************************************** + * + * GTP-C v2 Create Session Request + * Ref: 3GPP TS 29.274 v10.14.0 Table 7.2.1-1 + * + ***************************************************************************/ + +typedef struct gtpc_create_session_request +{ + bool imsi_present; + uint64_t imsi; // C + //bool msidn_present; + //uint64_t msisdn; // C + //bool mei_present; + //uint64_t mei; // C/CO + //bool user_location_info_present; + //struct gtpc_user_location_info_ie uli; // C/CO + //bool serving_network_present; + //struct gtpc_serving_network_ie serving_network; // C/CO + + enum gtpc_rat_type rat_type; // M + //bool indication_flags_present; + //struct indication_flags_ indication_flags; // C + + struct gtpc_f_teid_ie sender_f_teid; // M + bool pgw_addr_present; + struct gtpc_f_teid_ie pgw_addr; // C + + char[MAX_APN_LENGTH] apn; // M + //bool selection_mode_present; + //enum selection_mode_ selection_mode; // C/CO + //bool pdn_type_present; + //enum gtpc_pdn_type pdn_type; // C + //bool pdn_addr_alloc_present; + //struct pdn_addr_alloc_ pdn_addr_alloc; // C/CO + //bool max_apn_restriction_present; + //enum apn_restriction_ max_apn_restriction; // C + //bool apn_ambr_present; + //struct ambr_ apn_ambr; // C + //bool linked_eps_bearer_id_present; + //uint8_t linked_eps_bearer_id; // C + //bool pco_present; + //uint8_t pco; // C + + struct gtpc_bearer_context_ie bearer_context_created; // M + //bool bearer_context_deleted_present; + //struct bearer_context_ bearer_context_deleted; // C + //bool trace_information_present; + //struct trace_infromation_ trace_information; // C + //bool recovery_present + //uint8_t recovery; // C + //bool mme_fq_csid_present; + //struct fq_csid_ mme_fq_csid; // C + //bool sgw_fq_csid_present; + //struct fq_csid_ sgw_fq_csid; // C + //bool epdg_fq_csid_present; + //struct fq_csid_ epdg_fq_csid; // C + //bool ue_time_zone_present; + //struct ue_time_zone_ ue_time_zone; // CO + //bool uci_present; + //struct uci_ uci; // CO + //bool charging_caracteristics_present; + //enum charging_characteristics_ charging_caracteristics; // O + //bool mme_ldn_present; + //uint8_t mme_ldn[LDN_MAX_SIZE]; // O + //bool sgw_ldn_present; + //uint8_t sgw_ldn[LDN_MAX_SIZE]; // O + //bool epgd_ldn_present; + //uint8_t epdg_ldn[LDN_MAX_SIZE]; // O + //bool signaling_priority_indication; + //enum signalling_priority_indication_ spi; // CO + //bool acpo_present; + //uint8_t apco; // CO + //bool ext; // O +} gtpc_create_session_request_t; + + +}; //namespace +#endif //GTPC_V2_MSG_H diff --git a/srsepc/src/mme/mme_gtpc.cc b/srsepc/src/mme/mme_gtpc.cc index 413e4e50f..aafcf367b 100644 --- a/srsepc/src/mme/mme_gtpc.cc +++ b/srsepc/src/mme/mme_gtpc.cc @@ -84,7 +84,7 @@ mme_gtpc::send_create_session_request(uint64_t imsi, struct create_session_respo //Setup GTP-C Create Session Request IEs // Control TEID allocated \\ cs_req->sender_f_teid.tied = get_new_ctrl_teid(); - cs_req->sender_f_teid.ip = m_mme_gtpc_ip; + cs_req->sender_f_teid.ipv4 = m_mme_gtpc_ip; // APN \\ memcpy(cs_req->apn, "internet", sizeof("internet")); // RAT Type \\ From ff32f31c9bbf856e248dcc11313206b27ce94d35 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 23 Nov 2017 12:45:30 +0000 Subject: [PATCH 082/172] Added structures to create session request. Starting to add create session response structure --- lib/include/srslte/asn1/gtpc_ies.h | 24 ++++++++++++++++++------ lib/include/srslte/asn1/gtpc_msg.h | 20 ++++++++++++++++++-- srsepc/src/mme/mme_gtpc.cc | 4 ++-- srsepc/src/mme/s1ap.cc | 3 ++- 4 files changed, 40 insertions(+), 11 deletions(-) diff --git a/lib/include/srslte/asn1/gtpc_ies.h b/lib/include/srslte/asn1/gtpc_ies.h index e643b8f41..24652be5b 100644 --- a/lib/include/srslte/asn1/gtpc_ies.h +++ b/lib/include/srslte/asn1/gtpc_ies.h @@ -27,8 +27,6 @@ #include "srslte/phy/io/netsource.h" -//#include -//#include /**************************************************************** * @@ -135,7 +133,7 @@ enum gtpc_ie_type GTPC_IE_TYPE_TMGI = 158, GTPC_IE_TYPE_ADDITIONAL_MM_CONTEXT_FOR_SRVCC = 159, GTPC_IE_TYPE_ADDITIONAL_FLAGS_FOR_SRVCC = 160, -//161 RESERVED +//161 RESERVED GTPC_IE_TYPE_MDT_CONFIGURATION = 162, GTPC_IE_TYPE_APCO = 163, //164 RESERVED @@ -241,7 +239,7 @@ struct gtpc_ambr_ie * ***************************************************************************/ /* - * IP addresses should the sockaddr_storage struct, which can hold IPv4 + * IP addresse IEs should the sockaddr_storage struct, which can hold IPv4 * and IPv6 addresses. */ @@ -321,8 +319,22 @@ struct gtpc_f_teid_ie bool v6_present; enum gtpc_interface_type interface_type; uint32_t teid; - struct in_addr ipv4; - struct in6_addr ipv6; + in_addr_t ipv4; + struct in6_addr ipv6; //FIXME }; +//TODO +//TODO IEs between 8.22 and 8.28 missing +//TODO + +/**************************************************************************** + * + * GTP-C Bearer Context IE + * Ref: 3GPP TS 29.274 v10.14.0 Table 8.28-1 + * + ***************************************************************************/ +//The usage of this grouped IE is specific to the GTP-C message being sent. +//As such, each GTP-C message will define it's bearer context structures +//locally, according to the rules of TS 29.274 v10.14.0 Section 7. + #endif //GTPC_IES_H diff --git a/lib/include/srslte/asn1/gtpc_msg.h b/lib/include/srslte/asn1/gtpc_msg.h index ccb2c7ae4..efb429217 100644 --- a/lib/include/srslte/asn1/gtpc_msg.h +++ b/lib/include/srslte/asn1/gtpc_msg.h @@ -170,7 +170,7 @@ typedef struct gtpc_create_session_request bool pgw_addr_present; struct gtpc_f_teid_ie pgw_addr; // C - char[MAX_APN_LENGTH] apn; // M + char apn[MAX_APN_LENGTH]; // M //bool selection_mode_present; //enum selection_mode_ selection_mode; // C/CO //bool pdn_type_present; @@ -186,7 +186,23 @@ typedef struct gtpc_create_session_request //bool pco_present; //uint8_t pco; // C - struct gtpc_bearer_context_ie bearer_context_created; // M + struct gtpc_bearer_context_created_ie //see TS 29.274 v10.14.0 Table 7.2.1-2 + { + uint8_t ebi; + bool tft_present; + bool s1_u_enodeb_f_teid_present; + struct gtpc_f_teid_ie s1_u_enodeb_f_teid; + bool s4_u_sgsn_f_teid_present; + struct gtpc_f_teid_ie s4_u_sgsn_f_teid; + bool s5_s8_u_sgw_f_teid_present; + struct gtpc_f_teid_ie s5_s8_u_sgw_f_teid; + bool s5_s8_u_pgw_f_teid_present; + struct gtpc_f_teid_ie s5_s8_u_pgw_f_teid; + bool s12_rnc_f_teid_present; + struct gtpc_f_teid_ie s12_rnc_f_teid; + bool s2b_u_epdg_f_teid_present; + struct gtpc_f_teid_ie s2b_u_epdg_f_teid; + } bearer_context_created; // M //bool bearer_context_deleted_present; //struct bearer_context_ bearer_context_deleted; // C //bool trace_information_present; diff --git a/srsepc/src/mme/mme_gtpc.cc b/srsepc/src/mme/mme_gtpc.cc index aafcf367b..3e62a0bcb 100644 --- a/srsepc/src/mme/mme_gtpc.cc +++ b/srsepc/src/mme/mme_gtpc.cc @@ -91,9 +91,9 @@ mme_gtpc::send_create_session_request(uint64_t imsi, struct create_session_respo cs_req->rat_type = GTPC_RAT_TYPE::EUTRAN; //Save RX Control TEID - create_rx_control_teid(cs_req->sender_f_tied); + //create_rx_control_teid(cs_req->sender_f_teid); - spgw->handle_create_session_request(&cs_req, cs_resp); + //spgw->handle_create_session_request(&cs_req, cs_resp); return; } } //namespace srsepc diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index a334d47dc..7dc3648ee 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -487,7 +487,8 @@ s1ap::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, srslte: //FIXME The packging of GTP-C messages is not ready //This means that GTP-U tunnels are created with function calls, as oposed to GTP-C. //In future send_create_session_request will return void and the handle_create_session_response will be called from the GTP-C class itself. - struct gtpc_create_session_response *cs_resp = m_gtpc->send_create_session_request(ue_ctx->imsi); + struct gtpc_create_session_response cs_resp; + m_gtpc->send_create_session_request(ue_ctx->imsi, &cs_resp); m_gtpc->handle_create_session_response(cs_resp); } return true; From 2172662388f453b559faee28d0708208c03980dd Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 23 Nov 2017 14:57:21 +0000 Subject: [PATCH 083/172] Added initial create session response structure. Compiling now. --- lib/include/srslte/asn1/gtpc_msg.h | 46 ++++++++++++++++++++++++++++-- srsepc/hdr/mme/mme_gtpc.h | 4 +-- srsepc/src/mme/mme_gtpc.cc | 2 +- srsepc/src/mme/s1ap.cc | 10 +++---- 4 files changed, 52 insertions(+), 10 deletions(-) diff --git a/lib/include/srslte/asn1/gtpc_msg.h b/lib/include/srslte/asn1/gtpc_msg.h index efb429217..d25d64484 100644 --- a/lib/include/srslte/asn1/gtpc_msg.h +++ b/lib/include/srslte/asn1/gtpc_msg.h @@ -149,7 +149,7 @@ const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_STOP_RESPONSE = 236; * ***************************************************************************/ -typedef struct gtpc_create_session_request +struct gtpc_create_session_request { bool imsi_present; uint64_t imsi; // C @@ -232,8 +232,50 @@ typedef struct gtpc_create_session_request //bool acpo_present; //uint8_t apco; // CO //bool ext; // O -} gtpc_create_session_request_t; +}; + /**************************************************************************** + * + * GTP-C v2 Create Session Response + * Ref: 3GPP TS 29.274 v10.14.0 Table 7.2.2-1 + * + ***************************************************************************/ +struct gtpc_create_session_response +{ + struct gtpc_cause_ie cause; //M + //Change Reporting Action //C + //CSG Information Reporting Action //CO + bool sender_f_teid_present; + struct gtpc_f_teid_ie sender_f_teid; //C + //PGW S5/S8/S2b F-TEID //C + //struct gtpc_pdn_address_allocation_ie pdn_address_allocation; //C + //apn_restriction + //apn_ambr + //linked_eps_bearer_id + //pco + struct gtpc_bearer_context_created_ie + { + uint8_t ebi; + // + } bearer_context_created; //M + + /* + struct gtpc_bearer_context_removed_ie + { + uint8_t ebi; + // + } bearer_context_removed; //C + */ + //recovery; //C + //charging_gateway_name; //C + //charging_gateway_address; //C + //PGW-FQ-CSID //C + //SGW-FQ-CSID //C + //SGW LDN //O + //PGW LDN //O + //PGW Back-Off Time //O + //acpo //CO +}; }; //namespace #endif //GTPC_V2_MSG_H diff --git a/srsepc/hdr/mme/mme_gtpc.h b/srsepc/hdr/mme/mme_gtpc.h index a393cfe56..22a4e6463 100644 --- a/srsepc/hdr/mme/mme_gtpc.h +++ b/srsepc/hdr/mme/mme_gtpc.h @@ -29,7 +29,7 @@ #include "srslte/common/buffer_pool.h" #include #include "spgw/spgw.h" - +#include "srslte/asn1/gtpc.h" namespace srsepc { @@ -41,7 +41,7 @@ public: static void cleanup(void); void init(); - void send_create_session_request(uint64_t imsi, struct create_session_response *cs_resp); + void send_create_session_request(uint64_t imsi, struct srslte::gtpc_create_session_response *cs_resp); private: diff --git a/srsepc/src/mme/mme_gtpc.cc b/srsepc/src/mme/mme_gtpc.cc index 3e62a0bcb..2c27b3f7f 100644 --- a/srsepc/src/mme/mme_gtpc.cc +++ b/srsepc/src/mme/mme_gtpc.cc @@ -70,7 +70,7 @@ mme_gtpc::init() } void -mme_gtpc::send_create_session_request(uint64_t imsi, struct create_session_response *cs_resp) +mme_gtpc::send_create_session_request(uint64_t imsi, struct srslte::gtpc_create_session_response *cs_resp) { struct srslte::gtpc_pdu cs_req_pdu; struct srslte::gtpc_create_session_request *cs_req = &cs_req_pdu.choice.create_session_request; diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 7dc3648ee..f2dcaa6a5 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -28,6 +28,7 @@ #include #include "srslte/common/bcd_helpers.h" #include "mme/s1ap.h" +#include "srslte/asn1/gtpc.h" namespace srsepc{ @@ -484,12 +485,11 @@ s1ap::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, srslte: //Send Security Mode Command m_s1ap_nas_transport.pack_security_mode_command(reply_msg, ue_ctx); - //FIXME The packging of GTP-C messages is not ready - //This means that GTP-U tunnels are created with function calls, as oposed to GTP-C. - //In future send_create_session_request will return void and the handle_create_session_response will be called from the GTP-C class itself. - struct gtpc_create_session_response cs_resp; + //FIXME The packging of GTP-C messages is not ready. + //This means that GTP-U tunnels are created with function calls, as opposed to GTP-C. + struct srslte::gtpc_create_session_response cs_resp; m_gtpc->send_create_session_request(ue_ctx->imsi, &cs_resp); - m_gtpc->handle_create_session_response(cs_resp); + //m_gtpc->handle_create_session_response(cs_resp); } return true; } From 2e6050bf381e4a0856bf7a4759f674708b984721 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 23 Nov 2017 18:11:53 +0000 Subject: [PATCH 084/172] Started to fill in the necessary information for the create session response. --- srsepc/hdr/mme/mme_gtpc.h | 3 + srsepc/hdr/spgw/spgw.h | 14 ++- srsepc/src/mme/mme_gtpc.cc | 11 +- srsepc/src/spgw/spgw.cc | 227 ++++++++++++++++++++++--------------- 4 files changed, 159 insertions(+), 96 deletions(-) diff --git a/srsepc/hdr/mme/mme_gtpc.h b/srsepc/hdr/mme/mme_gtpc.h index 22a4e6463..c6d2286dd 100644 --- a/srsepc/hdr/mme/mme_gtpc.h +++ b/srsepc/hdr/mme/mme_gtpc.h @@ -42,6 +42,7 @@ public: void init(); void send_create_session_request(uint64_t imsi, struct srslte::gtpc_create_session_response *cs_resp); + uint64_t get_new_ctrl_teid(); private: @@ -53,6 +54,8 @@ private: spgw* m_spgw; in_addr_t m_mme_gtpc_ip; + + uint64_t m_next_ctrl_teid; }; } diff --git a/srsepc/hdr/spgw/spgw.h b/srsepc/hdr/spgw/spgw.h index eb75ed57d..0b62ae87b 100644 --- a/srsepc/hdr/spgw/spgw.h +++ b/srsepc/hdr/spgw/spgw.h @@ -39,6 +39,7 @@ #include "srslte/common/log_filter.h" #include "srslte/common/buffer_pool.h" #include "srslte/common/threads.h" +#include "srslte/asn1/gtpc.h" namespace srsepc{ @@ -50,6 +51,15 @@ typedef struct { } spgw_args_t; +typedef struct { + uint64_t imsi; + in_addr_t ue_ipv4; + struct gtpc_f_teid_ie uplink_ctrl; + struct gtpc_f_teid_ie uplink_user; + struct gtpc_f_teid_ie downlink_ctrl; + struct gtpc_f_teid_ie downlink_user; +} spgw_ue_ctxr; + class spgw: public thread { @@ -60,6 +70,8 @@ public: void stop(); void run_thread(); + void handle_create_session_request(struct srslte::gtpc_create_session_request *cs_req, struct srslte::gtpc_create_session_response *cs_resp); + private: spgw(); @@ -81,7 +93,7 @@ private: /*Logs*/ srslte::log_filter *m_spgw_log; - + }; } // namespace srsepc diff --git a/srsepc/src/mme/mme_gtpc.cc b/srsepc/src/mme/mme_gtpc.cc index 2c27b3f7f..4fd6fbbf1 100644 --- a/srsepc/src/mme/mme_gtpc.cc +++ b/srsepc/src/mme/mme_gtpc.cc @@ -34,6 +34,7 @@ mme_gtpc* mme_gtpc::m_instance = NULL; boost::mutex mme_gtpc_instance_mutex; mme_gtpc::mme_gtpc() + :m_next_ctrl_teid(1) { } @@ -69,12 +70,20 @@ mme_gtpc::init() m_spgw = spgw::get_instance(); } +uint64_t +mme_gtpc::get_new_ctrl_teid() +{ + return m_next_ctrl_teid++; //FIXME Use a Id pool? +} void mme_gtpc::send_create_session_request(uint64_t imsi, struct srslte::gtpc_create_session_response *cs_resp) { struct srslte::gtpc_pdu cs_req_pdu; struct srslte::gtpc_create_session_request *cs_req = &cs_req_pdu.choice.create_session_request; + //Initialize GTP-C message to zero + bzero(&cs_req_pdu, sizeof(struct srslte::gtpc_pdu)); + //Setup GTP-C Header. FIXME: Length, sequence and other fields need to be added. cs_req_pdu.header.piggyback = false; cs_req_pdu.header.teid_present = true; @@ -93,7 +102,7 @@ mme_gtpc::send_create_session_request(uint64_t imsi, struct srslte::gtpc_create_ //Save RX Control TEID //create_rx_control_teid(cs_req->sender_f_teid); - //spgw->handle_create_session_request(&cs_req, cs_resp); + m_spgw->handle_create_session_request(cs_req, cs_resp); return; } } //namespace srsepc diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index 5f0a3d87f..1f1f2e70e 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -35,6 +35,7 @@ #include #include "spgw/spgw.h" + namespace srsepc{ spgw* spgw::m_instance = NULL; @@ -128,6 +129,106 @@ spgw::stop() return; } +srslte::error_t +spgw::init_sgi_if(spgw_args_t *args) +{ + char dev[IFNAMSIZ] = "srs_spgw_sgi"; + struct ifreq ifr; + + if(m_sgi_up) + { + return(srslte::ERROR_ALREADY_STARTED); + } + + + // Construct the TUN device + m_sgi_if = open("/dev/net/tun", O_RDWR); + m_spgw_log->info("TUN file descriptor = %d\n", m_sgi_if); + if(m_sgi_if < 0) + { + m_spgw_log->error("Failed to open TUN device: %s\n", strerror(errno)); + return(srslte::ERROR_CANT_START); + } + + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TUN | IFF_NO_PI; + strncpy(ifr.ifr_ifrn.ifrn_name, dev, IFNAMSIZ); + if(ioctl(m_sgi_if, TUNSETIFF, &ifr) < 0) + { + m_spgw_log->error("Failed to set TUN device name: %s\n", strerror(errno)); + close(m_sgi_if); + return(srslte::ERROR_CANT_START); + } + + // Bring up the interface + m_sgi_sock = socket(AF_INET, SOCK_DGRAM, 0); + + if(ioctl(m_sgi_sock, SIOCGIFFLAGS, &ifr) < 0) + { + m_spgw_log->error("Failed to bring up socket: %s\n", strerror(errno)); + close(m_sgi_if); + return(srslte::ERROR_CANT_START); + } + ifr.ifr_flags |= IFF_UP | IFF_RUNNING; + if(ioctl(m_sgi_sock, SIOCSIFFLAGS, &ifr) < 0) + { + m_spgw_log->error("Failed to set socket flags: %s\n", strerror(errno)); + close(m_sgi_if); + return(srslte::ERROR_CANT_START); + } + + //Set IP of the interface + struct sockaddr_in *addr = (struct sockaddr_in*)&ifr.ifr_addr; + addr->sin_family = AF_INET; + addr->sin_addr.s_addr = inet_addr(args->sgi_if_addr.c_str()); + addr->sin_port = 0; + + if (ioctl(m_sgi_sock, SIOCSIFADDR, &ifr) < 0) { + m_spgw_log->error("Failed to set TUN interface IP. Address: %s, Error: %s\n", args->sgi_if_addr.c_str(), strerror(errno)); + close(m_sgi_if); + close(m_sgi_sock); + return srslte::ERROR_CANT_START; + } + + ifr.ifr_netmask.sa_family = AF_INET; + ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr("255.255.255.0"); + if (ioctl(m_sgi_sock, SIOCSIFNETMASK, &ifr) < 0) { + m_spgw_log->error("Failed to set TUN interface Netmask. Error: %s\n", strerror(errno)); + close(m_sgi_if); + close(m_sgi_sock); + return srslte::ERROR_CANT_START; + } + + m_sgi_up = true; + return(srslte::ERROR_NONE); +} + +srslte::error_t +spgw::init_s1u(spgw_args_t *args) +{ + //Open S1-U socket + m_s1u = socket(AF_INET,SOCK_DGRAM,0); + if (m_s1u == -1) + { + m_spgw_log->error("Failed to open socket: %s\n", strerror(errno)); + return srslte::ERROR_CANT_START; + } + m_s1u_up = true; + + //Bind the socket + struct sockaddr_in servaddr; + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr=inet_addr(args->gtpu_bind_addr.c_str()); + servaddr.sin_port=htons(GTPU_RX_PORT); + + if (bind(m_s1u,(struct sockaddr *)&servaddr,sizeof(struct sockaddr_in))) { + m_spgw_log->error("Failed to bind socket: %s\n", strerror(errno)); + return srslte::ERROR_CANT_START; + } + m_spgw_log->info("S1-U socket = %d\n", m_s1u); + return srslte::ERROR_NONE; +} + void spgw::run_thread() { @@ -183,104 +284,42 @@ spgw::run_thread() return; } -srslte::error_t -spgw::init_sgi_if(spgw_args_t *args) + + + +void +spgw::handle_create_session_request(struct srslte::gtpc_create_session_request *cs_req, struct srslte::gtpc_create_session_response *cs_resp) { - char dev[IFNAMSIZ] = "srs_spgw_sgi"; - struct ifreq ifr; + //Setup uplink control TEID + uint64_t spgw_uplink_ctrl_teid = get_new_ctrl_teid(); + //Setup uplink user TEID + uint64_t spgw_uplink_user_teid = get_new_user_teid(); + //Allocate UE IP + in_addr_t ue_ip = get_new_ue_ipv4(); - if(m_sgi_up) - { - return(srslte::ERROR_ALREADY_STARTED); - } + //Save the UE context //TODO!!! - - // Construct the TUN device - m_sgi_if = open("/dev/net/tun", O_RDWR); - m_spgw_log->info("TUN file descriptor = %d\n", m_sgi_if); - if(m_sgi_if < 0) - { - m_spgw_log->error("Failed to open TUN device: %s\n", strerror(errno)); - return(srslte::ERROR_CANT_START); - } + //Create session response message + //Initialize to zero\\ + bzero(cs_resp,sizeof(struct srslte::gtpc_create_session_response)); + //Setup Cause\\ + cs_resp->cause = ; + //Setup sender F-TEID (ctrl)\\ + cs_resp->sender_f_teid.teid_present = true; + cs_resp->sender_f_teid.teid = spgw_uplink_ctrl_teid; + cs_resp->sender_f_teid.ipv4 = m_gtpu_bind_addr;//FIXME This is not relevant, as the GTP-C is not transmitted over sockets yet. + //Bearer context created\\ + cs_resp->eps_bearer_context_created.ebi = 5; + cs_resp->eps_bearer_context_created.cause = ; + cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid_present=true; + cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.teid = spgw_uplink_user_teid; + //Fill in the PDA\\ + cs_resp->pda_present = true; + cs_resp->pda.pdn_type = srslte::GTPC_IPV4; + cs_resp->ipv4_present = true; + cs_resp->ipv4 = ue_ip; - memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_flags = IFF_TUN | IFF_NO_PI; - strncpy(ifr.ifr_ifrn.ifrn_name, dev, IFNAMSIZ); - if(ioctl(m_sgi_if, TUNSETIFF, &ifr) < 0) - { - m_spgw_log->error("Failed to set TUN device name: %s\n", strerror(errno)); - close(m_sgi_if); - return(srslte::ERROR_CANT_START); - } - - // Bring up the interface - m_sgi_sock = socket(AF_INET, SOCK_DGRAM, 0); - - if(ioctl(m_sgi_sock, SIOCGIFFLAGS, &ifr) < 0) - { - m_spgw_log->error("Failed to bring up socket: %s\n", strerror(errno)); - close(m_sgi_if); - return(srslte::ERROR_CANT_START); - } - ifr.ifr_flags |= IFF_UP | IFF_RUNNING; - if(ioctl(m_sgi_sock, SIOCSIFFLAGS, &ifr) < 0) - { - m_spgw_log->error("Failed to set socket flags: %s\n", strerror(errno)); - close(m_sgi_if); - return(srslte::ERROR_CANT_START); - } - - //Set IP of the interface - struct sockaddr_in *addr = (struct sockaddr_in*)&ifr.ifr_addr; - addr->sin_family = AF_INET; - addr->sin_addr.s_addr = inet_addr(args->sgi_if_addr.c_str()); - addr->sin_port = 0; - - if (ioctl(m_sgi_sock, SIOCSIFADDR, &ifr) < 0) { - m_spgw_log->error("Failed to set TUN interface IP. Address: %s, Error: %s\n", args->sgi_if_addr.c_str(), strerror(errno)); - close(m_sgi_if); - close(m_sgi_sock); - return srslte::ERROR_CANT_START; - } - - ifr.ifr_netmask.sa_family = AF_INET; - ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr("255.255.255.0"); - if (ioctl(m_sgi_sock, SIOCSIFNETMASK, &ifr) < 0) { - m_spgw_log->error("Failed to set TUN interface Netmask. Error: %s\n", strerror(errno)); - close(m_sgi_if); - close(m_sgi_sock); - return srslte::ERROR_CANT_START; - } - - m_sgi_up = true; - return(srslte::ERROR_NONE); -} - -srslte::error_t -spgw::init_s1u(spgw_args_t *args) -{ - //Open S1-U socket - m_s1u = socket(AF_INET,SOCK_DGRAM,0); - if (m_s1u == -1) - { - m_spgw_log->error("Failed to open socket: %s\n", strerror(errno)); - return srslte::ERROR_CANT_START; - } - m_s1u_up = true; - - //Bind the socket - struct sockaddr_in servaddr; - servaddr.sin_family = AF_INET; - servaddr.sin_addr.s_addr=inet_addr(args->gtpu_bind_addr.c_str()); - servaddr.sin_port=htons(GTPU_RX_PORT); - - if (bind(m_s1u,(struct sockaddr *)&servaddr,sizeof(struct sockaddr_in))) { - m_spgw_log->error("Failed to bind socket: %s\n", strerror(errno)); - return srslte::ERROR_CANT_START; - } - m_spgw_log->info("S1-U socket = %d\n", m_s1u); - return srslte::ERROR_NONE; + return; } } //namespace srsepc From d76daf3db5a73c2d084520cf3d97918515f889f2 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 24 Nov 2017 11:36:49 +0000 Subject: [PATCH 085/172] Added GTP-C cause value enum. --- lib/include/srslte/asn1/gtpc_ies.h | 81 ++++++++++++++++++++++++++---- lib/include/srslte/asn1/gtpc_msg.h | 20 +++++++- srsepc/hdr/spgw/spgw.h | 5 ++ srsepc/src/spgw/spgw.cc | 26 ++++++++-- 4 files changed, 115 insertions(+), 17 deletions(-) diff --git a/lib/include/srslte/asn1/gtpc_ies.h b/lib/include/srslte/asn1/gtpc_ies.h index 24652be5b..2208b3d8f 100644 --- a/lib/include/srslte/asn1/gtpc_ies.h +++ b/lib/include/srslte/asn1/gtpc_ies.h @@ -163,18 +163,77 @@ enum gtpc_ie_type enum gtpc_cause_value { //Reserved - LOCAL_DETACH = 2, - COMPLETE_DETACH = 3, - RAT_CHANGED_FROM_3GPP_TO_NON_3GPP = 4, - ISR_DEACTIVATION = 5, - ERROR_INDICATION_RECEIVED_FROM_RNC_ENODEB_S4_SGSN = 6, - IMSI_DETACH_ONLY = 7, - REACTIVATION_REQUESTED = 8, - PDN_RECONNECTION_TO_THIS_APN_DISALLOWED = 9, - ACCESS_CHANGED_FROM_NON_3GPP_TO_3GPP = 10, - PDN_CONNECTION_INACTIVITY_TIMER_EXPIRES = 11 + GTPC_CAUSE_VALUE_LOCAL_DETACH = 2, + GTPC_CAUSE_VALUE_COMPLETE_DETACH = 3, + GTPC_CAUSE_VALUE_RAT_CHANGED_FROM_3GPP_TO_NON_3GPP = 4, + GTPC_CAUSE_VALUE_ISR_DEACTIVATION = 5, + GTPC_CAUSE_VALUE_ERROR_INDICATION_RECEIVED_FROM_RNC_ENODEB_S4_SGSN = 6, + GTPC_CAUSE_VALUE_IMSI_DETACH_ONLY = 7, + GTPC_CAUSE_VALUE_REACTIVATION_REQUESTED = 8, + GTPC_CAUSE_VALUE_PDN_RECONNECTION_TO_THIS_APN_DISALLOWED = 9, + GTPC_CAUSE_VALUE_ACCESS_CHANGED_FROM_NON_3GPP_TO_3GPP = 10, + GTPC_CAUSE_VALUE_PDN_CONNECTION_INACTIVITY_TIMER_EXPIRES = 11, //Spare. This value range shall be used by Cause values in an initial/request message. - + GTPC_CAUSE_VALUE_REQUEST_ACCEPTED = 16, + GTPC_CAUSE_VALUE_REQUEST_ACCEPTED_PARTIALLY = 17, + GTPC_CAUSE_VALUE_NEW_PDN_TYPE_DUE_TO_NETWORK_PREFERENCE = 18, + GTPC_CAUSE_VALUE_NEW_PDN_TYPE_DUE_TO_SINGLE_ADDRESS_BEARER_ONLY = 19, + //20-63 Spare. + GTPC_CAUSE_VALUE_CONTEXT_NOT_FOUND = 64, + GTPC_CAUSE_VALUE_INVALID_MESSAGE_FORMAT = 65, + GTPC_CAUSE_VALUE_VERSION_NOT_SUPPORTED_BY_NEXT_PEER = 66, + GTPC_CAUSE_VALUE_INVALID_LENGTH = 67, + GTPC_CAUSE_VALUE_SERVICE_NOT_SUPPORTED = 68, + GTPC_CAUSE_VALUE_MANDATORY_IE_INCORRECT = 69, + GTPC_CAUSE_VALUE_MANDATORY_IE_MISSING = 70, + //71 Shall not be used. + GTPC_CAUSE_VALUE_SYSTEM_FAILURE = 72, + GTPC_CAUSE_VALUE_NO_RESOURCES_AVAILABLE = 73, + GTPC_CAUSE_VALUE_SEMANTIC_ERROR_IN_THE_TFT_OPERATION = 74, + GTPC_CAUSE_VALUE_SYNTACTIC_ERROR_IN_THE_TFT_OPERATION = 75, + GTPC_CAUSE_VALUE_SEMANTIC_ERRORS_IN_PACKET_FILTER = 76, + GTPC_CAUSE_VALUE_SYNTACTIC_ERRORS_IN_PACKET_FILTER = 77, + GTPC_CAUSE_VALUE_MISSING_OR_UNKNOWN_APN = 78, + //79 Shall not be used. + GTPC_CAUSE_VALUE_GRE_KEY_NOT_FOUND = 80, + GTPC_CAUSE_VALUE_RELOCATION_FAILURE = 81, + GTPC_CAUSE_VALUE_DENIED_IN_RAT = 82, + GTPC_CAUSE_VALUE_PREFERRED_PDN_TYPE_NOT_SUPPORTED = 83, + GTPC_CAUSE_VALUE_ALL_DYNAMIC_ADDRESSES_ARE_OCCUPIED = 84, + GTPC_CAUSE_VALUE_UE_CONTEXT_WITHOUT_TFT_ALREADY_ACTIVATED = 85, + GTPC_CAUSE_VALUE_PROTOCOL_TYPE_NOT_SUPPORTED = 86, + GTPC_CAUSE_VALUE_UE_NOT_RESPONDING = 87, + GTPC_CAUSE_VALUE_UE_REFUSES = 88, + GTPC_CAUSE_VALUE_SERVICE_DENIED = 89, + GTPC_CAUSE_VALUE_UNABLE_TO_PAGE_UE = 90, + GTPC_CAUSE_VALUE_NO_MEMORY_AVAILABLE = 91, + GTPC_CAUSE_VALUE_USER_AUTHENTICATION_FAILED = 92, + GTPC_CAUSE_VALUE_APN_ACCESS_DENIED_NO_SUBSCRIPTION = 93, + GTPC_CAUSE_VALUE_REQUEST_REJECTED = 94, + GTPC_CAUSE_VALUE_P_TMSI_SIGNATURE_MISMATCH = 95, + GTPC_CAUSE_VALUE_IMSI_IMEI_NOT_KNOWN = 96, + GTPC_CAUSE_VALUE_SEMANTIC_ERROR_IN_THE_TAD_OPERATION = 97, + GTPC_CAUSE_VALUE_SYNTACTIC_ERROR_IN_THE_TAD_OPERATION = 98, + //99 Shall not be used. + GTPC_CAUSE_VALUE_REMOTE_PEER_NOT_RESPONDING = 100, + GTPC_CAUSE_VALUE_COLLISION_WITH_NETWORK_INITIATED_REQUEST = 101, + GTPC_CAUSE_VALUE_UNABLE_TO_PAGE_UE_DUE_TO_SUSPENSION = 102, + GTPC_CAUSE_VALUE_CONDITIONAL_IE_MISSING = 103, + GTPC_CAUSE_VALUE_APN_RESTRICTION_TYPE_INCOMPATIBLE_WITH_CURRENTLY_ACTIVE_PDN_CONNECTION = 104, + GTPC_CAUSE_VALUE_INVALID_OVERALL_LENGTH_OF_THE_TRIGGERED_RESPONSE_MSG_AND_A_PIGGYBACKED_INITIAL_MSG = 105, + GTPC_CAUSE_VALUE_DATA_FORWARDING_NOT_SUPPORTED = 106, + GTPC_CAUSE_VALUE_INVALID_REPLY_FROM_REMOTE_PEER = 107, + GTPC_CAUSE_VALUE_FALLBACK_TO_GTPV1 = 108, + GTPC_CAUSE_VALUE_INVALID_PEER = 109, + GTPC_CAUSE_VALUE_TEMPORARILY_REJECTED_DUE_TO_HANDOVER_PROCEDURE_IN_PROGRESS = 110, + GTPC_CAUSE_VALUE_MODIFICATIONS_NOT_LIMITED_TO_S1_U_BEARERS = 111, + GTPC_CAUSE_VALUE_REQUEST_REJECTED_FOR_A_PMIPV6_REASON = 112, + GTPC_CAUSE_VALUE_APN_CONGESTION = 113, + GTPC_CAUSE_VALUE_BEARER_HANDLING_NOT_SUPPORTED = 114, + GTPC_CAUSE_VALUE_UE_ALREADY_RE_ATTACHED = 115, + GTPC_CAUSE_VALUE_MULTIPLE_PDN_CONNECTIONS_FOR_A_GIVEN_APN_NOT_ALLOWED = 116 + //117-239 Spare. For future use in a triggered/response message. + //240-255 Spare. For future use in an initial/request message. }; struct gtpc_cause_ie diff --git a/lib/include/srslte/asn1/gtpc_msg.h b/lib/include/srslte/asn1/gtpc_msg.h index d25d64484..4fbcd35c1 100644 --- a/lib/include/srslte/asn1/gtpc_msg.h +++ b/lib/include/srslte/asn1/gtpc_msg.h @@ -256,8 +256,24 @@ struct gtpc_create_session_response struct gtpc_bearer_context_created_ie { uint8_t ebi; - // - } bearer_context_created; //M + gtpc_cause_ie cause; + bool s1_u_sgw_f_teid_present; + struct gtpc_f_teid_ie s1_u_sgw_f_teid; + bool s4_u_sgw_f_teid_present; + struct gtpc_f_teid_ie s4_u_sgw_f_teid; + bool s5_s8_u_pgw_f_teid_present; + struct gtpc_f_teid_ie s5_s8_u_pgw_f_teid; + bool s12_sgw_f_teid_present; + struct gtpc_f_teid_ie s12_sgw_f_teid; + bool s2b_u_pgw_f_teid_present; + struct gtpc_f_teid_ie s2b_u_pgw_f_teid; + //bearer_level_qos_present + //bearer_level_qos + //charging_id_present + //charging_id + //bearer_flags_present + //bearer_flags + } eps_bearer_context_created; //M /* struct gtpc_bearer_context_removed_ie diff --git a/srsepc/hdr/spgw/spgw.h b/srsepc/hdr/spgw/spgw.h index 0b62ae87b..7a1c5d6c3 100644 --- a/srsepc/hdr/spgw/spgw.h +++ b/srsepc/hdr/spgw/spgw.h @@ -80,6 +80,9 @@ private: srslte::error_t init_sgi_if(spgw_args_t *args); srslte::error_t init_s1u(spgw_args_t *args); + uint64_t get_new_ctrl_teid(); + uint64_t get_new_user_teid(); + in_addr_t get_new_ue_ipv4(); bool m_running; srslte::byte_buffer_pool *m_pool; @@ -91,6 +94,8 @@ private: bool m_s1u_up; int m_s1u; + uint64_t m_next_ctrl_teid; + uint64_t m_next_user_teid; /*Logs*/ srslte::log_filter *m_spgw_log; diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index 1f1f2e70e..6d43478db 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -46,9 +46,11 @@ const uint16_t SPGW_BUFFER_SIZE = 2500; spgw::spgw(): m_running(false), m_sgi_up(false), - m_s1u_up(false) + m_s1u_up(false), + m_next_ctrl_teid(1), + m_next_user_teid(1) { - m_pool = srslte::byte_buffer_pool::get_instance(); + m_pool = srslte::byte_buffer_pool::get_instance(); return; } @@ -285,7 +287,23 @@ spgw::run_thread() } +uint64_t +spgw::get_new_ctrl_teid() +{ + return m_next_ctrl_teid++; +} +uint64_t +spgw::get_new_user_teid() +{ + return m_next_user_teid++; +} + +in_addr_t +spgw::get_new_ue_ipv4() +{ + return inet_addr("172.0.0.2");//FIXME Tmp hack +} void spgw::handle_create_session_request(struct srslte::gtpc_create_session_request *cs_req, struct srslte::gtpc_create_session_response *cs_resp) @@ -307,7 +325,7 @@ spgw::handle_create_session_request(struct srslte::gtpc_create_session_request * //Setup sender F-TEID (ctrl)\\ cs_resp->sender_f_teid.teid_present = true; cs_resp->sender_f_teid.teid = spgw_uplink_ctrl_teid; - cs_resp->sender_f_teid.ipv4 = m_gtpu_bind_addr;//FIXME This is not relevant, as the GTP-C is not transmitted over sockets yet. + cs_resp->sender_f_teid.ipv4 = 0;//FIXME This is not relevant, as the GTP-C is not transmitted over sockets yet. //Bearer context created\\ cs_resp->eps_bearer_context_created.ebi = 5; cs_resp->eps_bearer_context_created.cause = ; @@ -318,7 +336,7 @@ spgw::handle_create_session_request(struct srslte::gtpc_create_session_request * cs_resp->pda.pdn_type = srslte::GTPC_IPV4; cs_resp->ipv4_present = true; cs_resp->ipv4 = ue_ip; - + return; } From ee21a277e5a96e901d155c4d03e97d57b176c390 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 24 Nov 2017 12:14:36 +0000 Subject: [PATCH 086/172] Added PAA information in the create session response. --- lib/include/srslte/asn1/gtpc_ies.h | 33 ++++++++++++++++++++++++++++-- lib/include/srslte/asn1/gtpc_msg.h | 2 +- srsepc/hdr/spgw/spgw.h | 8 ++++---- srsepc/src/spgw/spgw.cc | 12 +++++------ 4 files changed, 42 insertions(+), 13 deletions(-) diff --git a/lib/include/srslte/asn1/gtpc_ies.h b/lib/include/srslte/asn1/gtpc_ies.h index 2208b3d8f..ab3e00d43 100644 --- a/lib/include/srslte/asn1/gtpc_ies.h +++ b/lib/include/srslte/asn1/gtpc_ies.h @@ -25,9 +25,11 @@ #ifndef GTPC_IES_H #define GTPC_IES_H - #include "srslte/phy/io/netsource.h" +namespace srslte +{ + /**************************************************************** * * GTP-C IE Types @@ -303,7 +305,33 @@ struct gtpc_ambr_ie */ //TODO -//TODO IEs between 8.10 and 8.17 missing +//TODO IEs between 8.10 and 8.13 missing +//TODO + +/**************************************************************************** + * + * GTP-C PAA Type IE + * Ref: 3GPP TS 29.274 v10.14.0 Figure 8.14-1 + * + ***************************************************************************/ +enum gtpc_pdn_type +{ + GTPC_PDN_TYPE_IPV4 = 1, + GTPC_PDN_TYPE_IPV6 = 2, + GTPC_PDN_TYPE_IPV4V6 = 3 +}; + +struct gtpc_pdn_address_allocation_ie +{ + enum gtpc_pdn_type pdn_type; + bool ipv4_present; + bool ipv6_present; + in_addr_t ipv4; + struct in6_addr; +}; + +//TODO +//TODO IEs between 8.15 and 8.17 missing //TODO /**************************************************************************** @@ -396,4 +424,5 @@ struct gtpc_f_teid_ie //As such, each GTP-C message will define it's bearer context structures //locally, according to the rules of TS 29.274 v10.14.0 Section 7. +} //namespace #endif //GTPC_IES_H diff --git a/lib/include/srslte/asn1/gtpc_msg.h b/lib/include/srslte/asn1/gtpc_msg.h index 4fbcd35c1..4db2e9c6f 100644 --- a/lib/include/srslte/asn1/gtpc_msg.h +++ b/lib/include/srslte/asn1/gtpc_msg.h @@ -248,7 +248,7 @@ struct gtpc_create_session_response bool sender_f_teid_present; struct gtpc_f_teid_ie sender_f_teid; //C //PGW S5/S8/S2b F-TEID //C - //struct gtpc_pdn_address_allocation_ie pdn_address_allocation; //C + struct gtpc_pdn_address_allocation_ie paa; //C //apn_restriction //apn_ambr //linked_eps_bearer_id diff --git a/srsepc/hdr/spgw/spgw.h b/srsepc/hdr/spgw/spgw.h index 7a1c5d6c3..f6dceeb37 100644 --- a/srsepc/hdr/spgw/spgw.h +++ b/srsepc/hdr/spgw/spgw.h @@ -54,10 +54,10 @@ typedef struct { typedef struct { uint64_t imsi; in_addr_t ue_ipv4; - struct gtpc_f_teid_ie uplink_ctrl; - struct gtpc_f_teid_ie uplink_user; - struct gtpc_f_teid_ie downlink_ctrl; - struct gtpc_f_teid_ie downlink_user; + struct srslte::gtpc_f_teid_ie uplink_ctrl; + struct srslte::gtpc_f_teid_ie uplink_user; + struct srslte::gtpc_f_teid_ie downlink_ctrl; + struct srslte::gtpc_f_teid_ie downlink_user; } spgw_ue_ctxr; class spgw: diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index 6d43478db..d7d3a78c0 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -321,21 +321,21 @@ spgw::handle_create_session_request(struct srslte::gtpc_create_session_request * //Initialize to zero\\ bzero(cs_resp,sizeof(struct srslte::gtpc_create_session_response)); //Setup Cause\\ - cs_resp->cause = ; + cs_resp->cause.cause_value = srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED; //Setup sender F-TEID (ctrl)\\ cs_resp->sender_f_teid.teid_present = true; cs_resp->sender_f_teid.teid = spgw_uplink_ctrl_teid; cs_resp->sender_f_teid.ipv4 = 0;//FIXME This is not relevant, as the GTP-C is not transmitted over sockets yet. //Bearer context created\\ cs_resp->eps_bearer_context_created.ebi = 5; - cs_resp->eps_bearer_context_created.cause = ; + cs_resp->eps_bearer_context_created.cause.cause_value = srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED; cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid_present=true; cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.teid = spgw_uplink_user_teid; //Fill in the PDA\\ - cs_resp->pda_present = true; - cs_resp->pda.pdn_type = srslte::GTPC_IPV4; - cs_resp->ipv4_present = true; - cs_resp->ipv4 = ue_ip; + cs_resp->paa_present = true; + cs_resp->paa.pdn_type = srslte::GTPC_PDN_TYPE_IPV4; + cs_resp->paa.ipv4_present = true; + cs_resp->paa.ipv4 = ue_ip; return; } From 3c839c1c9bf6f408fdc972ba62a2b9ce7e898a56 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 24 Nov 2017 18:20:14 +0000 Subject: [PATCH 087/172] Starting to create Initial Context Setup request message. --- srsepc/hdr/mme/s1ap.h | 2 +- srsepc/src/mme/s1ap.cc | 97 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 89 insertions(+), 10 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index d51313c72..89f8fcac1 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -99,7 +99,7 @@ private: s1ap_nas_transport m_s1ap_nas_transport; //FIXME the GTP-C should be moved to the MME class, the the packaging of GTP-C messages is done. - mme_gtpc *m_gtpc; + mme_gtpc *m_mme_gtpc; }; diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index f2dcaa6a5..e58df02fe 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -54,7 +54,7 @@ s1ap::init(s1ap_args_t s1ap_args, srslte::log_filter *s1ap_log) m_s1ap_nas_transport.set_log(s1ap_log); m_hss = hss::get_instance(); - m_gtpc = mme_gtpc::get_instance(); + m_mme_gtpc = mme_gtpc::get_instance(); m_s1mme = enb_listen(); @@ -387,7 +387,7 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT uint32_t mme_ue_s1ap_id = ul_xport->MME_UE_S1AP_ID.MME_UE_S1AP_ID; ue_ctx_t *ue_ctx; - srslte::byte_buffer_t *reply_msg = m_pool->allocate(); + srslte::byte_buffer_t *reply_msg = m_pool->allocate(); m_s1ap_log->console("Received Uplink NAS Transport message. MME-UE S1AP Id: %d\n",mme_ue_s1ap_id); m_s1ap_log->info("Received Uplink NAS Transport message. MME-UE S1AP Id: %d\n",mme_ue_s1ap_id); @@ -409,7 +409,7 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT memcpy(nas_msg->msg, &ul_xport->NAS_PDU.buffer, ul_xport->NAS_PDU.n_octets); nas_msg->N_bytes = ul_xport->NAS_PDU.n_octets; liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &pd, &msg_type); - + switch (msg_type) { case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE: handle_nas_authentication_response(nas_msg, reply_msg, ue_ctx); @@ -424,7 +424,7 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT m_s1ap_log->info("Unhandled NAS message"); return false; //FIXME (nas_msg deallocate needs to be called) } - + //Send Reply to eNB ssize_t n_sent = sctp_send(m_s1mme,reply_msg->msg, reply_msg->N_bytes, enb_sri, 0); @@ -485,11 +485,6 @@ s1ap::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, srslte: //Send Security Mode Command m_s1ap_nas_transport.pack_security_mode_command(reply_msg, ue_ctx); - //FIXME The packging of GTP-C messages is not ready. - //This means that GTP-U tunnels are created with function calls, as opposed to GTP-C. - struct srslte::gtpc_create_session_response cs_resp; - m_gtpc->send_create_session_request(ue_ctx->imsi, &cs_resp); - //m_gtpc->handle_create_session_response(cs_resp); } return true; } @@ -517,9 +512,93 @@ s1ap::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, srslte:: m_s1ap_log->info("Received Security Mode Command Complete. IMSI: %lu\n", ue_ctx->imsi); m_s1ap_log->console("Received Security Mode Command Complete. IMSI: %lu\n", ue_ctx->imsi); + //FIXME The packging of GTP-C messages is not ready. + //This means that GTP-U tunnels are created with function calls, as opposed to GTP-C. + struct srslte::gtpc_create_session_response cs_resp; + m_mme_gtpc->send_create_session_request(ue_ctx->imsi, &cs_resp); + if (cs_resp.cause.cause_value != srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED){ + m_s1ap_log->warning("Could not create GTPC session.\n"); + //TODO Handle error + } + else{ + send_initial_context_setup_request(&cs_resp); + } return true; } +bool +s1ap::send_initial_context_setup_request(struct srslte::create_session_response *cs_resp) +{ + + LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT in_ctxt_req; + bzero(&in_ctxt_req, sizeof(in_ctxt_req)); + + in_ctxt_req.MME_UE_S1AP_ID =; + in_ctxt_req.eNB_UE_S1AP_ID =; + in_ctxt_req.uEaggregateMaximumBitrate =; + + //eRAB context to setup + LIBLTE_S1AP_E_RABSETUPITEMCTXTSURES_STRUCT *erab_ctxt = &in_ctxt_req.E_RABToBeSetupListCtxtSUReq.buffer[0]; //FIXME? + erab_ctxt->e_RAB_ID = cs_resp->bearer_context_created.ebi; + erab_ctxt->transportLayerAddress = cs_resp->bearer_context_created.sender_f_teid.ipv4; + erab_ctxt->gTP_TEID = cs_resp->bearer_context_created.sender_f_teid.teid; + + in_ctxt_req->UESecurityCapabilities =; + in_ctxt_req->SecurityKey = ; + + + /* + typedef struct{ + uint32_t len; + LIBLTE_S1AP_E_RABSETUPITEMCTXTSURES_STRUCT buffer[32]; //WARNING: Artificial limit to reduce memory footprint + }LIBLTE_S1AP_E_RABSETUPLISTCTXTSURES_STRUCT; + */ + /*typedef struct{ + bool ext; + LIBLTE_S1AP_E_RAB_ID_STRUCT e_RAB_ID; + LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT transportLayerAddress; + LIBLTE_S1AP_GTP_TEID_STRUCT gTP_TEID; + LIBLTE_S1AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; + bool iE_Extensions_present; + }LIBLTE_S1AP_E_RABSETUPITEMCTXTSURES_STRUCT; + */ + /*typedef struct{ + bool ext; + LIBLTE_S1AP_MME_UE_S1AP_ID_STRUCT MME_UE_S1AP_ID; + LIBLTE_S1AP_ENB_UE_S1AP_ID_STRUCT eNB_UE_S1AP_ID; + LIBLTE_S1AP_UEAGGREGATEMAXIMUMBITRATE_STRUCT uEaggregateMaximumBitrate; + LIBLTE_S1AP_E_RABTOBESETUPLISTCTXTSUREQ_STRUCT E_RABToBeSetupListCtxtSUReq; + LIBLTE_S1AP_UESECURITYCAPABILITIES_STRUCT UESecurityCapabilities; + LIBLTE_S1AP_SECURITYKEY_STRUCT SecurityKey; + LIBLTE_S1AP_TRACEACTIVATION_STRUCT TraceActivation; + bool TraceActivation_present; + LIBLTE_S1AP_HANDOVERRESTRICTIONLIST_STRUCT HandoverRestrictionList; + bool HandoverRestrictionList_present; + LIBLTE_S1AP_UERADIOCAPABILITY_STRUCT UERadioCapability; + bool UERadioCapability_present; + LIBLTE_S1AP_SUBSCRIBERPROFILEIDFORRFP_STRUCT SubscriberProfileIDforRFP; + bool SubscriberProfileIDforRFP_present; + LIBLTE_S1AP_CSFALLBACKINDICATOR_ENUM_EXT CSFallbackIndicator; + bool CSFallbackIndicator_present; + LIBLTE_S1AP_SRVCCOPERATIONPOSSIBLE_ENUM_EXT SRVCCOperationPossible; + bool SRVCCOperationPossible_present; + LIBLTE_S1AP_CSGMEMBERSHIPSTATUS_ENUM CSGMembershipStatus; + bool CSGMembershipStatus_present; + LIBLTE_S1AP_LAI_STRUCT RegisteredLAI; + bool RegisteredLAI_present; + LIBLTE_S1AP_GUMMEI_STRUCT GUMMEI_ID; + bool GUMMEI_ID_present; + LIBLTE_S1AP_MME_UE_S1AP_ID_STRUCT MME_UE_S1AP_ID_2; + bool MME_UE_S1AP_ID_2_present; + LIBLTE_S1AP_MANAGEMENTBASEDMDTALLOWED_ENUM_EXT ManagementBasedMDTAllowed; + bool ManagementBasedMDTAllowed_present; + LIBLTE_S1AP_MDTPLMNLIST_STRUCT ManagementBasedMDTPLMNList; + bool ManagementBasedMDTPLMNList_present; + LIBLTE_S1AP_ADDITIONALCSFALLBACKINDICATOR_ENUM_EXT AdditionalCSFallbackIndicator; + bool AdditionalCSFallbackIndicator_present; + }LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT;*/ + return true; +} bool s1ap::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri) { From fd6baaf15cef62d936017c7498f1635f658a921e Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 27 Nov 2017 15:38:10 +0000 Subject: [PATCH 088/172] Changed S1AP to singleton. Continuing to work on the intial context setup request. Added a TEID to MME_UE_S1AP_ID map. --- lib/include/srslte/asn1/gtpc.h | 1 + srsepc/hdr/mme/mme.h | 2 +- srsepc/hdr/mme/mme_gtpc.h | 12 +++++++++-- srsepc/hdr/mme/s1ap.h | 8 +++++++ srsepc/hdr/spgw/spgw.h | 7 +++++- srsepc/src/mme/mme.cc | 16 ++++++++------ srsepc/src/mme/mme_gtpc.cc | 18 ++++++++++++++-- srsepc/src/mme/s1ap.cc | 39 ++++++++++++++++++++++++++++------ srsepc/src/spgw/spgw.cc | 19 +++++++++++++++-- 9 files changed, 101 insertions(+), 21 deletions(-) diff --git a/lib/include/srslte/asn1/gtpc.h b/lib/include/srslte/asn1/gtpc.h index 362765935..ce46ab9e2 100644 --- a/lib/include/srslte/asn1/gtpc.h +++ b/lib/include/srslte/asn1/gtpc.h @@ -72,6 +72,7 @@ const uint8_t GTPC_V2 = 2; typedef union gtpc_msg_choice { struct gtpc_create_session_request create_session_request; + struct gtpc_create_session_response create_session_response; } gtpc_msg_choice_t; /**************************************************************************** diff --git a/srsepc/hdr/mme/mme.h b/srsepc/hdr/mme/mme.h index 2fec2a23a..555d39d58 100644 --- a/srsepc/hdr/mme/mme.h +++ b/srsepc/hdr/mme/mme.h @@ -76,7 +76,7 @@ private: mme(); virtual ~mme(); static mme *m_instance; - s1ap m_s1ap; + s1ap *m_s1ap; bool m_running; srslte::byte_buffer_pool *m_pool; diff --git a/srsepc/hdr/mme/mme_gtpc.h b/srsepc/hdr/mme/mme_gtpc.h index c6d2286dd..d003e9cc6 100644 --- a/srsepc/hdr/mme/mme_gtpc.h +++ b/srsepc/hdr/mme/mme_gtpc.h @@ -28,11 +28,14 @@ #include "srslte/common/buffer_pool.h" #include -#include "spgw/spgw.h" #include "srslte/asn1/gtpc.h" + namespace srsepc { +class spgw; +class s1ap; + class mme_gtpc { public: @@ -41,8 +44,10 @@ public: static void cleanup(void); void init(); - void send_create_session_request(uint64_t imsi, struct srslte::gtpc_create_session_response *cs_resp); + uint64_t get_new_ctrl_teid(); + void send_create_session_request(uint64_t imsi, struct srslte::gtpc_pdu *cs_resp_pdu); + void handle_create_session_response(srslte::gtpc_pdu *cs_resp_pdu); private: @@ -52,10 +57,13 @@ private: srslte::byte_buffer_pool *m_pool; + s1ap* m_s1ap; spgw* m_spgw; in_addr_t m_mme_gtpc_ip; uint64_t m_next_ctrl_teid; + std::map m_teid_to_mme_s1ap_id; + }; } diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 89f8fcac1..3fdfda9bc 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -26,6 +26,7 @@ #ifndef S1AP_H #define S1AP_H +#include "srslte/asn1/gtpc.h" #include "srslte/asn1/liblte_s1ap.h" #include "srslte/asn1/liblte_mme.h" #include "srslte/common/common.h" @@ -54,6 +55,10 @@ class s1ap public: s1ap(); virtual ~s1ap(); + + static s1ap* get_instance(); + static void cleanup(); + int enb_listen(); int init(s1ap_args_t s1ap_args, srslte::log_filter *s1ap_log); void stop(); @@ -76,11 +81,14 @@ public: bool handle_nas_authentication_response(srslte::byte_buffer_t *nas_buffer, srslte::byte_buffer_t *reply_buffer, ue_ctx_t *ue_ctx); bool handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx); + bool send_initial_context_setup_request(struct srslte::gtpc_create_session_response *cs_resp); void print_enb_ctx_info(const enb_ctx_t &enb_ctx); private: + static s1ap *m_instance; + s1ap_args_t m_s1ap_args; uint32_t m_plmn; srslte::byte_buffer_pool *m_pool; diff --git a/srsepc/hdr/spgw/spgw.h b/srsepc/hdr/spgw/spgw.h index f6dceeb37..12ec01d51 100644 --- a/srsepc/hdr/spgw/spgw.h +++ b/srsepc/hdr/spgw/spgw.h @@ -43,6 +43,8 @@ namespace srsepc{ +class mme_gtpc; + const uint16_t GTPU_RX_PORT = 2152; typedef struct { @@ -70,7 +72,7 @@ public: void stop(); void run_thread(); - void handle_create_session_request(struct srslte::gtpc_create_session_request *cs_req, struct srslte::gtpc_create_session_response *cs_resp); + void handle_create_session_request(struct srslte::gtpc_create_session_request *cs_req, struct srslte::gtpc_pdu *cs_resp_pdu); private: @@ -86,6 +88,8 @@ private: bool m_running; srslte::byte_buffer_pool *m_pool; + mme_gtpc *m_mme_gtpc; + bool m_sgi_up; int m_sgi_if; @@ -96,6 +100,7 @@ private: uint64_t m_next_ctrl_teid; uint64_t m_next_user_teid; + /*Logs*/ srslte::log_filter *m_spgw_log; diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index 8d45276e8..443ef84b3 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -72,9 +72,10 @@ mme::cleanup(void) int mme::init(mme_args_t* args, srslte::log_filter *s1ap_log) { - - /*Init S1AP*/ - if(m_s1ap.init(args->s1ap_args, s1ap_log)){ + + /*Init S1AP*/ + m_s1ap = s1ap::get_instance(); + if(m_s1ap->init(args->s1ap_args, s1ap_log)){ m_s1ap_log->error("Error initializing MME S1APP\n"); exit(-1); } @@ -91,7 +92,8 @@ mme::stop() { if(m_running) { - m_s1ap.stop(); + m_s1ap->stop(); + m_s1ap->cleanup(); m_running = false; thread_cancel(); wait_thread_finish(); @@ -116,7 +118,7 @@ mme::run_thread() m_running=true; //Get S1-MME socket - int s1mme = m_s1ap.get_s1_mme(); + int s1mme = m_s1ap->get_s1_mme(); while(m_running) { m_s1ap_log->debug("Waiting for SCTP Msg\n"); @@ -138,7 +140,7 @@ mme::run_thread() { m_s1ap_log->info("SCTP Association Shutdown. Association: %d\n",sri.sinfo_assoc_id); m_s1ap_log->console("SCTP Association Shutdown. Association: %d\n",sri.sinfo_assoc_id); - m_s1ap.delete_enb_ctx(sri.sinfo_assoc_id); + m_s1ap->delete_enb_ctx(sri.sinfo_assoc_id); } } else @@ -146,7 +148,7 @@ mme::run_thread() //Received data pdu->N_bytes = rd_sz; m_s1ap_log->info("Received S1AP msg. Size: %d\n", pdu->N_bytes); - m_s1ap.handle_s1ap_rx_pdu(pdu,&sri); + m_s1ap->handle_s1ap_rx_pdu(pdu,&sri); } } } diff --git a/srsepc/src/mme/mme_gtpc.cc b/srsepc/src/mme/mme_gtpc.cc index 4fd6fbbf1..9a65d78fa 100644 --- a/srsepc/src/mme/mme_gtpc.cc +++ b/srsepc/src/mme/mme_gtpc.cc @@ -27,6 +27,8 @@ #include #include "srslte/asn1/gtpc.h" #include "mme/mme_gtpc.h" +#include "mme/s1ap.h" +#include "spgw/spgw.h" namespace srsepc{ @@ -66,6 +68,7 @@ mme_gtpc::cleanup(void) void mme_gtpc::init() { + m_s1ap = s1ap::get_instance(); m_mme_gtpc_ip = inet_addr("127.0.0.1");//FIXME At the moment, the GTP-C messages are not sent over the wire. So this parameter is not used. m_spgw = spgw::get_instance(); } @@ -76,7 +79,7 @@ mme_gtpc::get_new_ctrl_teid() return m_next_ctrl_teid++; //FIXME Use a Id pool? } void -mme_gtpc::send_create_session_request(uint64_t imsi, struct srslte::gtpc_create_session_response *cs_resp) +mme_gtpc::send_create_session_request(uint64_t imsi, struct srslte::gtpc_pdu *cs_resp_pdu) { struct srslte::gtpc_pdu cs_req_pdu; struct srslte::gtpc_create_session_request *cs_req = &cs_req_pdu.choice.create_session_request; @@ -102,7 +105,18 @@ mme_gtpc::send_create_session_request(uint64_t imsi, struct srslte::gtpc_create_ //Save RX Control TEID //create_rx_control_teid(cs_req->sender_f_teid); - m_spgw->handle_create_session_request(cs_req, cs_resp); + m_spgw->handle_create_session_request(cs_req, cs_resp_pdu); return; } + +void +mme_gtpc::handle_create_session_response(srslte::gtpc_pdu *cs_resp_pdu) +{ + //Get MME_UE_S1AP_ID from the Ctrl TEID + std::map::iterator id_it = m_teid_to_mme_s1ap_id.find(cs_resp_pdu->header.teid); + uint32_t mme_s1ap_id = id_it->second; + + m_s1ap->send_intial_context_setup_request(mme_s1ap_id, &cs_resp_pdu->choice.create_session_request); +} + } //namespace srsepc diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index e58df02fe..e0f74b710 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -32,6 +32,9 @@ namespace srsepc{ +s1ap* s1ap::m_instance = NULL; +boost::mutex s1ap_instance_mutex; + s1ap::s1ap(): m_s1mme(-1), m_next_mme_ue_s1ap_id(1) @@ -42,6 +45,27 @@ s1ap::~s1ap() { } +s1ap* +s1ap::get_instance(void) +{ + boost::mutex::scoped_lock lock(s1ap_instance_mutex); + if(NULL == m_instance) { + m_instance = new mme(); + } + return(m_instance); +} + +void +s1ap::cleanup(void) +{ + boost::mutex::scoped_lock lock(s1ap_instance_mutex); + if(NULL != m_instance) { + delete m_instance; + m_instance = NULL; + } +} + + int s1ap::init(s1ap_args_t s1ap_args, srslte::log_filter *s1ap_log) { @@ -514,26 +538,29 @@ s1ap::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, srslte:: //FIXME The packging of GTP-C messages is not ready. //This means that GTP-U tunnels are created with function calls, as opposed to GTP-C. - struct srslte::gtpc_create_session_response cs_resp; - m_mme_gtpc->send_create_session_request(ue_ctx->imsi, &cs_resp); - if (cs_resp.cause.cause_value != srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED){ + struct srslte::gtpc_pdu cs_resp_pdu; + struct srslte::gtpc_create_session_response *cs_resp = & cs_resp_pdu.choice.create_session_response; + + m_mme_gtpc->send_create_session_request(ue_ctx->imsi, &cs_resp_pdu); + if (cs_resp->cause.cause_value != srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED){ m_s1ap_log->warning("Could not create GTPC session.\n"); //TODO Handle error } else{ - send_initial_context_setup_request(&cs_resp); + send_initial_context_setup_request(cs_resp); } return true; } bool -s1ap::send_initial_context_setup_request(struct srslte::create_session_response *cs_resp) +s1ap::send_initial_context_setup_request(struct srslte::gtpc_create_session_response *cs_resp) { LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT in_ctxt_req; + uint64_t imsi = m_mme_gtpc->ctrl_teid_to_imsi(); bzero(&in_ctxt_req, sizeof(in_ctxt_req)); - in_ctxt_req.MME_UE_S1AP_ID =; + in_ctxt_req.MME_UE_S1AP_ID = ; in_ctxt_req.eNB_UE_S1AP_ID =; in_ctxt_req.uEaggregateMaximumBitrate =; diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index d7d3a78c0..5c1675ef9 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -34,6 +34,7 @@ #include #include #include "spgw/spgw.h" +#include "mme/mme_gtpc.h" namespace srsepc{ @@ -86,6 +87,7 @@ spgw::init(spgw_args_t* args, srslte::log_filter *spgw_log) //Init log m_spgw_log = spgw_log; + m_mme_gtpc = mme_gtpc::get_instance(); //Init SGi interface err = init_sgi_if(args); @@ -306,8 +308,18 @@ spgw::get_new_ue_ipv4() } void -spgw::handle_create_session_request(struct srslte::gtpc_create_session_request *cs_req, struct srslte::gtpc_create_session_response *cs_resp) +spgw::handle_create_session_request(struct srslte::gtpc_create_session_request *cs_req, struct srslte::gtpc_pdu *cs_resp_pdu) { + srslte::gtpc_header *header = &cs_resp_pdu->header; + srslte::gtpc_create_session_response *cs_resp = &cs_resp_pdu->choice.create_session_response; + + //Setup GTP-C header + header->piggyback = false; + header->teid_present = true; + header->teid = cs_req->sender_f_teid.teid; //Send create session requesponse to the CS Request TEID + header->type = srslte::GTPC_MSG_TYPE_CREATE_SESSION_RESPONSE; + + //Setup uplink control TEID uint64_t spgw_uplink_ctrl_teid = get_new_ctrl_teid(); //Setup uplink user TEID @@ -315,7 +327,7 @@ spgw::handle_create_session_request(struct srslte::gtpc_create_session_request * //Allocate UE IP in_addr_t ue_ip = get_new_ue_ipv4(); - //Save the UE context //TODO!!! + //Save the UE IMSI to Ctrl TEID map //TODO!!! //Create session response message //Initialize to zero\\ @@ -337,7 +349,10 @@ spgw::handle_create_session_request(struct srslte::gtpc_create_session_request * cs_resp->paa.ipv4_present = true; cs_resp->paa.ipv4 = ue_ip; + m_mme_gtpc->handle_create_session_response(cs_resp_pdu); return; } + + } //namespace srsepc From 6cd055e80e1609752d579696028eaa9039520b4d Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 27 Nov 2017 19:13:34 +0000 Subject: [PATCH 089/172] Continuing to work on initial context setup request. --- lib/include/srslte/asn1/gtpc.h | 4 +++ lib/include/srslte/asn1/gtpc_msg.h | 2 +- srsepc/hdr/mme/mme_gtpc.h | 2 +- srsepc/hdr/mme/s1ap.h | 2 +- srsepc/src/mme/mme_gtpc.cc | 36 +++++++++++++++---- srsepc/src/mme/s1ap.cc | 57 +++++++++++++++++++----------- 6 files changed, 72 insertions(+), 31 deletions(-) diff --git a/lib/include/srslte/asn1/gtpc.h b/lib/include/srslte/asn1/gtpc.h index ce46ab9e2..8fdbab53d 100644 --- a/lib/include/srslte/asn1/gtpc.h +++ b/lib/include/srslte/asn1/gtpc.h @@ -27,6 +27,10 @@ #include #include "srslte/asn1/gtpc_msg.h" +//Helpful marcos to convert TEIDs (uint64_t) to/from network byte order +#define HTONLL(x) ((1==htonl(1)) ? (x) : (((uint64_t)htonl((x) & 0xFFFFFFFFUL)) << 32) | htonl((uint32_t)((x) >> 32))) +#define NTOHLL(x) ((1==ntohl(1)) ? (x) : (((uint64_t)ntohl((x) & 0xFFFFFFFFUL)) << 32) | ntohl((uint32_t)((x) >> 32))) + namespace srslte{ /*GTP-C Version*/ diff --git a/lib/include/srslte/asn1/gtpc_msg.h b/lib/include/srslte/asn1/gtpc_msg.h index 4db2e9c6f..a72e51ac9 100644 --- a/lib/include/srslte/asn1/gtpc_msg.h +++ b/lib/include/srslte/asn1/gtpc_msg.h @@ -202,7 +202,7 @@ struct gtpc_create_session_request struct gtpc_f_teid_ie s12_rnc_f_teid; bool s2b_u_epdg_f_teid_present; struct gtpc_f_teid_ie s2b_u_epdg_f_teid; - } bearer_context_created; // M + } eps_bearer_context_created; // M //bool bearer_context_deleted_present; //struct bearer_context_ bearer_context_deleted; // C //bool trace_information_present; diff --git a/srsepc/hdr/mme/mme_gtpc.h b/srsepc/hdr/mme/mme_gtpc.h index d003e9cc6..db886f137 100644 --- a/srsepc/hdr/mme/mme_gtpc.h +++ b/srsepc/hdr/mme/mme_gtpc.h @@ -46,7 +46,7 @@ public: void init(); uint64_t get_new_ctrl_teid(); - void send_create_session_request(uint64_t imsi, struct srslte::gtpc_pdu *cs_resp_pdu); + void send_create_session_request(uint64_t imsi, uint32_t mme_s1ap_id); void handle_create_session_response(srslte::gtpc_pdu *cs_resp_pdu); private: diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 3fdfda9bc..ebf4ae60d 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -81,7 +81,7 @@ public: bool handle_nas_authentication_response(srslte::byte_buffer_t *nas_buffer, srslte::byte_buffer_t *reply_buffer, ue_ctx_t *ue_ctx); bool handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx); - bool send_initial_context_setup_request(struct srslte::gtpc_create_session_response *cs_resp); + bool send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp); void print_enb_ctx_info(const enb_ctx_t &enb_ctx); diff --git a/srsepc/src/mme/mme_gtpc.cc b/srsepc/src/mme/mme_gtpc.cc index 9a65d78fa..58c1d3ef2 100644 --- a/srsepc/src/mme/mme_gtpc.cc +++ b/srsepc/src/mme/mme_gtpc.cc @@ -79,11 +79,14 @@ mme_gtpc::get_new_ctrl_teid() return m_next_ctrl_teid++; //FIXME Use a Id pool? } void -mme_gtpc::send_create_session_request(uint64_t imsi, struct srslte::gtpc_pdu *cs_resp_pdu) +mme_gtpc::send_create_session_request(uint64_t imsi, uint32_t mme_ue_s1ap_id) { struct srslte::gtpc_pdu cs_req_pdu; struct srslte::gtpc_create_session_request *cs_req = &cs_req_pdu.choice.create_session_request; + struct srslte::gtpc_pdu cs_resp_pdu; + + //Initialize GTP-C message to zero bzero(&cs_req_pdu, sizeof(struct srslte::gtpc_pdu)); @@ -95,7 +98,7 @@ mme_gtpc::send_create_session_request(uint64_t imsi, struct srslte::gtpc_pdu *cs //Setup GTP-C Create Session Request IEs // Control TEID allocated \\ - cs_req->sender_f_teid.tied = get_new_ctrl_teid(); + cs_req->sender_f_teid.teid = get_new_ctrl_teid(); cs_req->sender_f_teid.ipv4 = m_mme_gtpc_ip; // APN \\ memcpy(cs_req->apn, "internet", sizeof("internet")); @@ -103,20 +106,39 @@ mme_gtpc::send_create_session_request(uint64_t imsi, struct srslte::gtpc_pdu *cs cs_req->rat_type = GTPC_RAT_TYPE::EUTRAN; //Save RX Control TEID - //create_rx_control_teid(cs_req->sender_f_teid); + m_teid_to_mme_s1ap_id.insert(std::pair(cs_req->sender_f_teid.teid, mme_ue_s1ap_id)); - m_spgw->handle_create_session_request(cs_req, cs_resp_pdu); - return; + m_spgw->handle_create_session_request(cs_req, &cs_resp_pdu); + handle_create_session_response(&cs_resp_pdu); + } void mme_gtpc::handle_create_session_response(srslte::gtpc_pdu *cs_resp_pdu) { + struct srslte::gtpc_create_session_response *cs_resp = & cs_resp_pdu->choice.create_session_response; + + if (cs_resp_pdu->header.type != srslte::GTPC_MSG_TYPE_CREATE_SESSION_RESPONSE) + { + //m_mme_gtpc_log->warning("Could not create GTPC session.\n"); + //TODO Handle err + return; + } + if (cs_resp->cause.cause_value != srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED){ + //m_mme_gtpc_log->warning("Could not create GTPC session.\n"); + //TODO Handle error + return; + } + //Get MME_UE_S1AP_ID from the Ctrl TEID std::map::iterator id_it = m_teid_to_mme_s1ap_id.find(cs_resp_pdu->header.teid); + if(id_it == m_teid_to_mme_s1ap_id.end()) + { + //Could not find MME UE S1AP TEID + return; + } uint32_t mme_s1ap_id = id_it->second; - - m_s1ap->send_intial_context_setup_request(mme_s1ap_id, &cs_resp_pdu->choice.create_session_request); + m_s1ap->send_initial_context_setup_request(mme_s1ap_id, cs_resp); } } //namespace srsepc diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index e0f74b710..3ceed89bb 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -50,7 +50,7 @@ s1ap::get_instance(void) { boost::mutex::scoped_lock lock(s1ap_instance_mutex); if(NULL == m_instance) { - m_instance = new mme(); + m_instance = new s1ap(); } return(m_instance); } @@ -538,37 +538,41 @@ s1ap::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, srslte:: //FIXME The packging of GTP-C messages is not ready. //This means that GTP-U tunnels are created with function calls, as opposed to GTP-C. - struct srslte::gtpc_pdu cs_resp_pdu; - struct srslte::gtpc_create_session_response *cs_resp = & cs_resp_pdu.choice.create_session_response; + m_mme_gtpc->send_create_session_request(ue_ctx->imsi, ue_ctx->mme_ue_s1ap_id); - m_mme_gtpc->send_create_session_request(ue_ctx->imsi, &cs_resp_pdu); - if (cs_resp->cause.cause_value != srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED){ - m_s1ap_log->warning("Could not create GTPC session.\n"); - //TODO Handle error - } - else{ - send_initial_context_setup_request(cs_resp); - } return true; } bool -s1ap::send_initial_context_setup_request(struct srslte::gtpc_create_session_response *cs_resp) +s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp) { + //Find UE Context + ue_ctx_t *ue_ctx; + std::map::iterator ue_ctx_it = m_active_ues.find(mme_ue_s1ap_id); + if(ue_ctx_it == m_active_ues.end()) + { + m_s1ap_log->error("Could not find UE to send Setup Context Request. MME S1AP Id: %d", mme_ue_s1ap_id); + return false; + } + ue_ctx = ue_ctx_it->second; + LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT in_ctxt_req; - uint64_t imsi = m_mme_gtpc->ctrl_teid_to_imsi(); bzero(&in_ctxt_req, sizeof(in_ctxt_req)); - in_ctxt_req.MME_UE_S1AP_ID = ; - in_ctxt_req.eNB_UE_S1AP_ID =; - in_ctxt_req.uEaggregateMaximumBitrate =; - + in_ctxt_req.MME_UE_S1AP_ID.MME_UE_S1AP_ID = ue_ctx->mme_ue_s1ap_id; + in_ctxt_req.eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ue_ctx->enb_ue_s1ap_id; + in_ctxt_req.uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL.BitRate=4294967295;//2^32-1 + in_ctxt_req.uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL.BitRate=4294967295;//FIXME Get UE-AMBR from HSS //eRAB context to setup - LIBLTE_S1AP_E_RABSETUPITEMCTXTSURES_STRUCT *erab_ctxt = &in_ctxt_req.E_RABToBeSetupListCtxtSUReq.buffer[0]; //FIXME? - erab_ctxt->e_RAB_ID = cs_resp->bearer_context_created.ebi; - erab_ctxt->transportLayerAddress = cs_resp->bearer_context_created.sender_f_teid.ipv4; - erab_ctxt->gTP_TEID = cs_resp->bearer_context_created.sender_f_teid.teid; + LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT *erab_ctxt = &in_ctxt_req.E_RABToBeSetupListCtxtSUReq.buffer[0]; //FIXME? + erab_ctxt->e_RAB_ID.E_RAB_ID = cs_resp->eps_bearer_context_created.ebi; + if (cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid_present == false){ + m_s1ap_log->error("Did not receive S1-U TEID in create session response\n"); + return false; + } + erab_ctxt->transportLayerAddress = cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.ipv4; + memcpy(erab_ctxt->gTP_TEID.buffer, cs_resp->eps_bearer_context_created.sender_f_teid.teid, sizeof(uint64_t)); in_ctxt_req->UESecurityCapabilities =; in_ctxt_req->SecurityKey = ; @@ -589,6 +593,17 @@ s1ap::send_initial_context_setup_request(struct srslte::gtpc_create_session_resp bool iE_Extensions_present; }LIBLTE_S1AP_E_RABSETUPITEMCTXTSURES_STRUCT; */ + /*typedef struct{ + bool ext; + uint32_t n_bits; + uint8_t buffer[160]; + }LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT; + */ + /* + typedef struct{ + uint8_t buffer[4]; + }LIBLTE_S1AP_GTP_TEID_STRUCT; + */ /*typedef struct{ bool ext; LIBLTE_S1AP_MME_UE_S1AP_ID_STRUCT MME_UE_S1AP_ID; From 831f7b00b6052b5d182f0517e24eb5df3a6393fe Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 27 Nov 2017 19:14:37 +0000 Subject: [PATCH 090/172] Changed TEID to network byte order. --- srsepc/src/mme/s1ap.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 3ceed89bb..fcdb6f58c 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -571,8 +571,12 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: m_s1ap_log->error("Did not receive S1-U TEID in create session response\n"); return false; } + erab_ctxt->transportLayerAddress = cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.ipv4; - memcpy(erab_ctxt->gTP_TEID.buffer, cs_resp->eps_bearer_context_created.sender_f_teid.teid, sizeof(uint64_t)); + + uint64_t tmp_teid; + tmp_teid = HTONLL(cs_resp->eps_bearer_context_created.sender_f_teid.teid); + memcpy(erab_ctxt->gTP_TEID.buffer, tmp_teid, sizeof(uint64_t)); in_ctxt_req->UESecurityCapabilities =; in_ctxt_req->SecurityKey = ; From 5bd630ad1559bb9f325c6a63d0d09f1fd3bc8eef Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 28 Nov 2017 15:48:44 +0000 Subject: [PATCH 091/172] Finalizing Context setup request. Compiling now. --- srsepc/hdr/mme/s1ap_common.h | 16 +++++++++-- srsepc/src/mme/s1ap.cc | 41 ++++++++++++++++++++-------- srsepc/src/mme/s1ap_nas_transport.cc | 2 +- 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/srsepc/hdr/mme/s1ap_common.h b/srsepc/hdr/mme/s1ap_common.h index 496518ca0..3ce8260d2 100644 --- a/srsepc/hdr/mme/s1ap_common.h +++ b/srsepc/hdr/mme/s1ap_common.h @@ -21,6 +21,10 @@ #ifndef S1AP_COMMON_H #define S1AP_COMMON_H +#include "srslte/common/security.h" + +namespace srsepc{ + static const uint8_t MAX_TA=255; //Maximum TA supported static const uint8_t MAX_BPLMN=6; //Maximum broadcasted PLMNs per TAC @@ -52,8 +56,14 @@ typedef struct{ uint64_t imsi; uint32_t enb_ue_s1ap_id; uint32_t mme_ue_s1ap_id; - uint8_t xres[8]; - uint8_t k_asme[32]; + struct eps_security_ctxt{ + uint8_t k_asme[32]; + uint8_t xres[8]; + uint32_t dl_nas_count; + uint32_t ul_nas_count; + srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo; + srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo; + } security_ctxt; } ue_ctx_t; - +}//namespace #endif diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index fcdb6f58c..182515549 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -29,6 +29,7 @@ #include "srslte/common/bcd_helpers.h" #include "mme/s1ap.h" #include "srslte/asn1/gtpc.h" +#include "srslte/common/liblte_security.h" namespace srsepc{ @@ -365,7 +366,7 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini m_s1ap_log->console("EPS Bearer id: %d\n", eps_bearer_id); //Get Authentication Vectors from HSS - if(!m_hss->gen_auth_info_answer_milenage(imsi, ue_ctx.k_asme, autn, rand, ue_ctx.xres)) + if(!m_hss->gen_auth_info_answer_milenage(imsi, ue_ctx.security_ctxt.k_asme, autn, rand, ue_ctx.security_ctxt.xres)) { m_s1ap_log->console("User not found. IMSI %015lu\n",imsi); m_s1ap_log->info("User not found. IMSI %015lu\n",imsi); @@ -481,7 +482,7 @@ s1ap::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, srslte: for(int i=0; i<8;i++) { - if(auth_resp.res[i] != ue_ctx->xres[i]) + if(auth_resp.res[i] != ue_ctx->security_ctxt.xres[i]) { ue_valid = false; } @@ -492,7 +493,7 @@ s1ap::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, srslte: std::cout<<"XRES: "; for(int i=0;i<8;i++) { - std::cout << std::hex <<(uint16_t)ue_ctx->xres[i]; + std::cout << std::hex <<(uint16_t)ue_ctx->security_ctxt.xres[i]; } std::cout<error("Did not receive S1-U TEID in create session response\n"); return false; } + uint32_t sgw_s1u_ip = cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.ipv4; + uint8_t *tmp_ptr = erab_ctxt->transportLayerAddress.buffer; + liblte_value_2_bits(sgw_s1u_ip, &tmp_ptr, 32);//FIXME consider ipv6 - erab_ctxt->transportLayerAddress = cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.ipv4; + uint32_t tmp_teid = cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.teid; + memcpy(erab_ctxt->gTP_TEID.buffer, &tmp_teid, sizeof(uint32_t)); - uint64_t tmp_teid; - tmp_teid = HTONLL(cs_resp->eps_bearer_context_created.sender_f_teid.teid); - memcpy(erab_ctxt->gTP_TEID.buffer, tmp_teid, sizeof(uint64_t)); + in_ctxt_req.UESecurityCapabilities.encryptionAlgorithms.buffer[0] = 0; //EEA0 + in_ctxt_req.UESecurityCapabilities.integrityProtectionAlgorithms.buffer[0] = 1; //EIA1 - in_ctxt_req->UESecurityCapabilities =; - in_ctxt_req->SecurityKey = ; - - + uint8_t key_enb[32]; + liblte_security_generate_k_enb(ue_ctx->security_ctxt.k_asme, ue_ctx->security_ctxt.dl_nas_count, key_enb); + liblte_unpack(key_enb, 32, in_ctxt_req.SecurityKey.buffer); + //liblte_value_2_bits(key_enb,,LIBLTE_S1AP_SECURITYKEY_BIT_STRING_LEN); + /* + typedef struct{ + bool ext; + uint8_t buffer[16]; + }LIBLTE_S1AP_INTEGRITYPROTECTIONALGORITHMS_STRUCT; + */ /* typedef struct{ uint32_t len; @@ -608,6 +618,15 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: uint8_t buffer[4]; }LIBLTE_S1AP_GTP_TEID_STRUCT; */ + /* + typedef struct{ + bool ext; + LIBLTE_S1AP_ENCRYPTIONALGORITHMS_STRUCT encryptionAlgorithms; + LIBLTE_S1AP_INTEGRITYPROTECTIONALGORITHMS_STRUCT integrityProtectionAlgorithms; + LIBLTE_S1AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; + bool iE_Extensions_present; + }LIBLTE_S1AP_UESECURITYCAPABILITIES_STRUCT; + */ /*typedef struct{ bool ext; LIBLTE_S1AP_MME_UE_S1AP_ID_STRUCT MME_UE_S1AP_ID; diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 0d8ab035a..62828d9f6 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -293,7 +293,7 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, uint8_t k_nas_enc[32]; uint8_t k_nas_int[32]; - srslte::security_generate_k_nas( ue_ctx->k_asme, + srslte::security_generate_k_nas( ue_ctx->security_ctxt.k_asme, srslte::CIPHERING_ALGORITHM_ID_EEA0, srslte::INTEGRITY_ALGORITHM_ID_128_EIA1, k_nas_enc, From 103361deb97cd192450686335373170a3dd7fa99 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 28 Nov 2017 17:52:57 +0000 Subject: [PATCH 092/172] Fixed SPGW initialization bug. --- lib/src/asn1/gtpc.cc | 2 +- srsepc/hdr/mme/mme.h | 1 + srsepc/hdr/mme/mme_gtpc.h | 2 +- srsepc/src/mme/mme.cc | 14 ++++++++++++-- srsepc/src/mme/mme_gtpc.cc | 4 +++- srsepc/src/spgw/spgw.cc | 2 +- 6 files changed, 19 insertions(+), 6 deletions(-) diff --git a/lib/src/asn1/gtpc.cc b/lib/src/asn1/gtpc.cc index d5c7320de..ac0116840 100644 --- a/lib/src/asn1/gtpc.cc +++ b/lib/src/asn1/gtpc.cc @@ -31,7 +31,7 @@ namespace srslte{ int -gtpc_pack_create_session_request(gtpc_create_session_request_t, srslte::byte_buffer_t) +gtpc_pack_create_session_request(struct gtpc_create_session_request *cs_req, srslte::byte_buffer_t) { //FIXME return 0; diff --git a/srsepc/hdr/mme/mme.h b/srsepc/hdr/mme/mme.h index 555d39d58..6016ebb75 100644 --- a/srsepc/hdr/mme/mme.h +++ b/srsepc/hdr/mme/mme.h @@ -77,6 +77,7 @@ private: virtual ~mme(); static mme *m_instance; s1ap *m_s1ap; + mme_gtpc *m_mme_gtpc; bool m_running; srslte::byte_buffer_pool *m_pool; diff --git a/srsepc/hdr/mme/mme_gtpc.h b/srsepc/hdr/mme/mme_gtpc.h index db886f137..3b8ed3901 100644 --- a/srsepc/hdr/mme/mme_gtpc.h +++ b/srsepc/hdr/mme/mme_gtpc.h @@ -43,7 +43,7 @@ public: static mme_gtpc* get_instance(void); static void cleanup(void); - void init(); + bool init(); uint64_t get_new_ctrl_teid(); void send_create_session_request(uint64_t imsi, uint32_t mme_s1ap_id); diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index 443ef84b3..07016b66d 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -73,6 +73,9 @@ int mme::init(mme_args_t* args, srslte::log_filter *s1ap_log) { + /*Init logger*/ + m_s1ap_log = s1ap_log; + /*Init S1AP*/ m_s1ap = s1ap::get_instance(); if(m_s1ap->init(args->s1ap_args, s1ap_log)){ @@ -80,8 +83,15 @@ mme::init(mme_args_t* args, srslte::log_filter *s1ap_log) exit(-1); } - /*Init logger*/ - m_s1ap_log = s1ap_log; + /*Init GTP-C*/ + m_mme_gtpc = mme_gtpc::get_instance(); + if(!m_mme_gtpc->init()) + { + m_s1ap_log->console("Error initializing GTP-C\n"); + exit(-1); + } + + /*Log successful initialization*/ m_s1ap_log->info("MME Initialized. MCC: %d, MNC: %d\n",args->s1ap_args.mcc, args->s1ap_args.mnc); m_s1ap_log->console("MME Initialized. \n"); return 0; diff --git a/srsepc/src/mme/mme_gtpc.cc b/srsepc/src/mme/mme_gtpc.cc index 58c1d3ef2..7e5c87d7b 100644 --- a/srsepc/src/mme/mme_gtpc.cc +++ b/srsepc/src/mme/mme_gtpc.cc @@ -65,12 +65,14 @@ mme_gtpc::cleanup(void) } -void +bool mme_gtpc::init() { m_s1ap = s1ap::get_instance(); m_mme_gtpc_ip = inet_addr("127.0.0.1");//FIXME At the moment, the GTP-C messages are not sent over the wire. So this parameter is not used. m_spgw = spgw::get_instance(); + + return true; } uint64_t diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index 5c1675ef9..a9e833b18 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -51,7 +51,6 @@ spgw::spgw(): m_next_ctrl_teid(1), m_next_user_teid(1) { - m_pool = srslte::byte_buffer_pool::get_instance(); return; } @@ -84,6 +83,7 @@ int spgw::init(spgw_args_t* args, srslte::log_filter *spgw_log) { srslte::error_t err; + m_pool = srslte::byte_buffer_pool::get_instance(); //Init log m_spgw_log = spgw_log; From c1d550ddabab6198d5424c9a4b3cd833581c0c04 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 28 Nov 2017 19:33:53 +0000 Subject: [PATCH 093/172] Starting the code to send ctx setup request to eNB --- srsepc/src/mme/s1ap.cc | 124 +++++++++++++---------------------------- 1 file changed, 38 insertions(+), 86 deletions(-) diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 182515549..7b933c349 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -547,9 +547,12 @@ s1ap::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, srslte:: bool s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp) { - - //Find UE Context ue_ctx_t *ue_ctx; + + LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT in_ctxt_req; + LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT *erab_ctxt = &in_ctxt_req.E_RABToBeSetupListCtxtSUReq.buffer[0]; //FIXME support more than one erab + srslte::byte_buffer_t *reply_buffer = m_pool->allocate(); + //Find UE Context std::map::iterator ue_ctx_it = m_active_ues.find(mme_ue_s1ap_id); if(ue_ctx_it == m_active_ues.end()) { @@ -558,20 +561,23 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: } ue_ctx = ue_ctx_it->second; - LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT in_ctxt_req; + //Add MME and eNB S1AP Ids bzero(&in_ctxt_req, sizeof(in_ctxt_req)); - in_ctxt_req.MME_UE_S1AP_ID.MME_UE_S1AP_ID = ue_ctx->mme_ue_s1ap_id; in_ctxt_req.eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ue_ctx->enb_ue_s1ap_id; + + //Set UE-AMBR in_ctxt_req.uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL.BitRate=4294967295;//2^32-1 in_ctxt_req.uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL.BitRate=4294967295;//FIXME Get UE-AMBR from HSS + //eRAB context to setup - LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT *erab_ctxt = &in_ctxt_req.E_RABToBeSetupListCtxtSUReq.buffer[0]; //FIXME? erab_ctxt->e_RAB_ID.E_RAB_ID = cs_resp->eps_bearer_context_created.ebi; if (cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid_present == false){ m_s1ap_log->error("Did not receive S1-U TEID in create session response\n"); return false; } + + //Set S-GW F-TEID uint32_t sgw_s1u_ip = cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.ipv4; uint8_t *tmp_ptr = erab_ctxt->transportLayerAddress.buffer; liblte_value_2_bits(sgw_s1u_ip, &tmp_ptr, 32);//FIXME consider ipv6 @@ -579,96 +585,42 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: uint32_t tmp_teid = cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.teid; memcpy(erab_ctxt->gTP_TEID.buffer, &tmp_teid, sizeof(uint32_t)); + //Set UE security capabilities and k_enb in_ctxt_req.UESecurityCapabilities.encryptionAlgorithms.buffer[0] = 0; //EEA0 in_ctxt_req.UESecurityCapabilities.integrityProtectionAlgorithms.buffer[0] = 1; //EIA1 uint8_t key_enb[32]; liblte_security_generate_k_enb(ue_ctx->security_ctxt.k_asme, ue_ctx->security_ctxt.dl_nas_count, key_enb); liblte_unpack(key_enb, 32, in_ctxt_req.SecurityKey.buffer); - //liblte_value_2_bits(key_enb,,LIBLTE_S1AP_SECURITYKEY_BIT_STRING_LEN); - /* - typedef struct{ - bool ext; - uint8_t buffer[16]; - }LIBLTE_S1AP_INTEGRITYPROTECTIONALGORITHMS_STRUCT; - */ - /* - typedef struct{ - uint32_t len; - LIBLTE_S1AP_E_RABSETUPITEMCTXTSURES_STRUCT buffer[32]; //WARNING: Artificial limit to reduce memory footprint - }LIBLTE_S1AP_E_RABSETUPLISTCTXTSURES_STRUCT; - */ - /*typedef struct{ - bool ext; - LIBLTE_S1AP_E_RAB_ID_STRUCT e_RAB_ID; - LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT transportLayerAddress; - LIBLTE_S1AP_GTP_TEID_STRUCT gTP_TEID; - LIBLTE_S1AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; - bool iE_Extensions_present; - }LIBLTE_S1AP_E_RABSETUPITEMCTXTSURES_STRUCT; - */ - /*typedef struct{ - bool ext; - uint32_t n_bits; - uint8_t buffer[160]; - }LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT; - */ - /* - typedef struct{ - uint8_t buffer[4]; - }LIBLTE_S1AP_GTP_TEID_STRUCT; - */ - /* - typedef struct{ - bool ext; - LIBLTE_S1AP_ENCRYPTIONALGORITHMS_STRUCT encryptionAlgorithms; - LIBLTE_S1AP_INTEGRITYPROTECTIONALGORITHMS_STRUCT integrityProtectionAlgorithms; - LIBLTE_S1AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; - bool iE_Extensions_present; - }LIBLTE_S1AP_UESECURITYCAPABILITIES_STRUCT; - */ - /*typedef struct{ - bool ext; - LIBLTE_S1AP_MME_UE_S1AP_ID_STRUCT MME_UE_S1AP_ID; - LIBLTE_S1AP_ENB_UE_S1AP_ID_STRUCT eNB_UE_S1AP_ID; - LIBLTE_S1AP_UEAGGREGATEMAXIMUMBITRATE_STRUCT uEaggregateMaximumBitrate; - LIBLTE_S1AP_E_RABTOBESETUPLISTCTXTSUREQ_STRUCT E_RABToBeSetupListCtxtSUReq; - LIBLTE_S1AP_UESECURITYCAPABILITIES_STRUCT UESecurityCapabilities; - LIBLTE_S1AP_SECURITYKEY_STRUCT SecurityKey; - LIBLTE_S1AP_TRACEACTIVATION_STRUCT TraceActivation; - bool TraceActivation_present; - LIBLTE_S1AP_HANDOVERRESTRICTIONLIST_STRUCT HandoverRestrictionList; - bool HandoverRestrictionList_present; - LIBLTE_S1AP_UERADIOCAPABILITY_STRUCT UERadioCapability; - bool UERadioCapability_present; - LIBLTE_S1AP_SUBSCRIBERPROFILEIDFORRFP_STRUCT SubscriberProfileIDforRFP; - bool SubscriberProfileIDforRFP_present; - LIBLTE_S1AP_CSFALLBACKINDICATOR_ENUM_EXT CSFallbackIndicator; - bool CSFallbackIndicator_present; - LIBLTE_S1AP_SRVCCOPERATIONPOSSIBLE_ENUM_EXT SRVCCOperationPossible; - bool SRVCCOperationPossible_present; - LIBLTE_S1AP_CSGMEMBERSHIPSTATUS_ENUM CSGMembershipStatus; - bool CSGMembershipStatus_present; - LIBLTE_S1AP_LAI_STRUCT RegisteredLAI; - bool RegisteredLAI_present; - LIBLTE_S1AP_GUMMEI_STRUCT GUMMEI_ID; - bool GUMMEI_ID_present; - LIBLTE_S1AP_MME_UE_S1AP_ID_STRUCT MME_UE_S1AP_ID_2; - bool MME_UE_S1AP_ID_2_present; - LIBLTE_S1AP_MANAGEMENTBASEDMDTALLOWED_ENUM_EXT ManagementBasedMDTAllowed; - bool ManagementBasedMDTAllowed_present; - LIBLTE_S1AP_MDTPLMNLIST_STRUCT ManagementBasedMDTPLMNList; - bool ManagementBasedMDTPLMNList_present; - LIBLTE_S1AP_ADDITIONALCSFALLBACKINDICATOR_ENUM_EXT AdditionalCSFallbackIndicator; - bool AdditionalCSFallbackIndicator_present; - }LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT;*/ + + //Set Attach accepted and activate defaulte bearer NAS messages + //TODO + + //Pack everything and send it to the eNB + + LIBLTE_ERROR_ENUM err = liblte_s1ap_pack_s1ap_pdu(&in_ctxt_req, (LIBLTE_BYTE_MSG_STRUCT*)reply_buffer); + if(err != LIBLTE_SUCCESS) + { + m_s1ap_log->error("Could not pack Initial Context Setup Request Message\n"); + return false; + } + //Send Reply to eNB + ssize_t n_sent = sctp_send(m_s1mme,reply_msg->msg, reply_msg->N_bytes, enb_sri, 0); + if(n_sent == -1) + { + m_s1ap_log->error("Failed to send Initial Context Setup Request\n"); + return false; + } + + + m_pool->deallocate(reply_buffer); return true; } -bool -s1ap::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri) -{ + bool + s1ap::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri) + { - uint32_t mme_ue_s1ap_id = ue_rel->MME_UE_S1AP_ID.MME_UE_S1AP_ID; + uint32_t mme_ue_s1ap_id = ue_rel->MME_UE_S1AP_ID.MME_UE_S1AP_ID; m_s1ap_log->info("Received UE Context Release Request. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); m_s1ap_log->console("Received UE Context Release Request. MME-UE S1AP Id %d\n", mme_ue_s1ap_id); From 5598e10ed685c0d1202f0e1a3ce370212d526b79 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 28 Nov 2017 23:27:53 +0000 Subject: [PATCH 094/172] commit to switch computer --- srsepc/src/mme/s1ap.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 7b933c349..d862f62b5 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -548,7 +548,6 @@ bool s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp) { ue_ctx_t *ue_ctx; - LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT in_ctxt_req; LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT *erab_ctxt = &in_ctxt_req.E_RABToBeSetupListCtxtSUReq.buffer[0]; //FIXME support more than one erab srslte::byte_buffer_t *reply_buffer = m_pool->allocate(); @@ -597,8 +596,11 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: //TODO //Pack everything and send it to the eNB + LIBLTE_S1AP_S1AP_PDU pdu; - LIBLTE_ERROR_ENUM err = liblte_s1ap_pack_s1ap_pdu(&in_ctxt_req, (LIBLTE_BYTE_MSG_STRUCT*)reply_buffer); + + + LIBLTE_ERROR_ENUM err = liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)reply_buffer); if(err != LIBLTE_SUCCESS) { m_s1ap_log->error("Could not pack Initial Context Setup Request Message\n"); From 425f5d22b55e0a53e86e09735aef13a5569aeb0b Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 29 Nov 2017 12:01:53 +0000 Subject: [PATCH 095/172] Starting to send Initial Context Setup Request to eNB. --- srsepc/hdr/mme/s1ap_common.h | 2 ++ srsepc/src/mme/s1ap.cc | 39 ++++++++++++++++++++++-------------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/srsepc/hdr/mme/s1ap_common.h b/srsepc/hdr/mme/s1ap_common.h index 3ce8260d2..a3ac54dab 100644 --- a/srsepc/hdr/mme/s1ap_common.h +++ b/srsepc/hdr/mme/s1ap_common.h @@ -56,6 +56,8 @@ typedef struct{ uint64_t imsi; uint32_t enb_ue_s1ap_id; uint32_t mme_ue_s1ap_id; + uint16_t enb_id; + struct sctp_sndrcvinfo enb_sri; struct eps_security_ctxt{ uint8_t k_asme[32]; uint8_t xres[8]; diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index d862f62b5..b4064efd6 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -365,6 +365,9 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini uint8_t proc_transaction_id = pdn_con_req.proc_transaction_id; //TODO: Transaction ID unused m_s1ap_log->console("EPS Bearer id: %d\n", eps_bearer_id); + //Add eNB info to UE ctxt + memcpy(&ue_ctx.enb_sri, &enb_sri, sizeof(struct sctp_sndrcvinfo)); + //Get Authentication Vectors from HSS if(!m_hss->gen_auth_info_answer_milenage(imsi, ue_ctx.security_ctxt.k_asme, autn, rand, ue_ctx.security_ctxt.xres)) { @@ -548,9 +551,19 @@ bool s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp) { ue_ctx_t *ue_ctx; - LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT in_ctxt_req; - LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT *erab_ctxt = &in_ctxt_req.E_RABToBeSetupListCtxtSUReq.buffer[0]; //FIXME support more than one erab + + //Prepare reply PDU + LIBLTE_S1AP_S1AP_PDU_STRUCT pdu; + pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE; + + LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *init = &pdu.choice.initiatingMessage; + init->procedureCode = LIBLTE_S1AP_PROC_ID_INITIALCONTEXTSETUP; + init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_INITIALCONTEXTSETUPREQUEST; + + LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT *in_ctxt_req = &init->choice.InitialContextSetupRequest; + LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT *erab_ctxt = &in_ctxt_req->E_RABToBeSetupListCtxtSUReq.buffer[0]; //FIXME support more than one erab srslte::byte_buffer_t *reply_buffer = m_pool->allocate(); + //Find UE Context std::map::iterator ue_ctx_it = m_active_ues.find(mme_ue_s1ap_id); if(ue_ctx_it == m_active_ues.end()) @@ -562,12 +575,12 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: //Add MME and eNB S1AP Ids bzero(&in_ctxt_req, sizeof(in_ctxt_req)); - in_ctxt_req.MME_UE_S1AP_ID.MME_UE_S1AP_ID = ue_ctx->mme_ue_s1ap_id; - in_ctxt_req.eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ue_ctx->enb_ue_s1ap_id; + in_ctxt_req->MME_UE_S1AP_ID.MME_UE_S1AP_ID = ue_ctx->mme_ue_s1ap_id; + in_ctxt_req->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ue_ctx->enb_ue_s1ap_id; //Set UE-AMBR - in_ctxt_req.uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL.BitRate=4294967295;//2^32-1 - in_ctxt_req.uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL.BitRate=4294967295;//FIXME Get UE-AMBR from HSS + in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL.BitRate=4294967295;//2^32-1 + in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL.BitRate=4294967295;//FIXME Get UE-AMBR from HSS //eRAB context to setup erab_ctxt->e_RAB_ID.E_RAB_ID = cs_resp->eps_bearer_context_created.ebi; @@ -585,20 +598,16 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: memcpy(erab_ctxt->gTP_TEID.buffer, &tmp_teid, sizeof(uint32_t)); //Set UE security capabilities and k_enb - in_ctxt_req.UESecurityCapabilities.encryptionAlgorithms.buffer[0] = 0; //EEA0 - in_ctxt_req.UESecurityCapabilities.integrityProtectionAlgorithms.buffer[0] = 1; //EIA1 + in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer[0] = 0; //EEA0 + in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[0] = 1; //EIA1 uint8_t key_enb[32]; liblte_security_generate_k_enb(ue_ctx->security_ctxt.k_asme, ue_ctx->security_ctxt.dl_nas_count, key_enb); - liblte_unpack(key_enb, 32, in_ctxt_req.SecurityKey.buffer); + liblte_unpack(key_enb, 32, in_ctxt_req->SecurityKey.buffer); //Set Attach accepted and activate defaulte bearer NAS messages //TODO - //Pack everything and send it to the eNB - LIBLTE_S1AP_S1AP_PDU pdu; - - LIBLTE_ERROR_ENUM err = liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)reply_buffer); if(err != LIBLTE_SUCCESS) @@ -607,13 +616,13 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: return false; } //Send Reply to eNB - ssize_t n_sent = sctp_send(m_s1mme,reply_msg->msg, reply_msg->N_bytes, enb_sri, 0); + ssize_t n_sent = sctp_send(m_s1mme,reply_buffer->msg, reply_buffer->N_bytes, &ue_ctx->enb_sri, 0); if(n_sent == -1) { m_s1ap_log->error("Failed to send Initial Context Setup Request\n"); return false; } - + m_pool->deallocate(reply_buffer); return true; From 13595ccb2d94e433067d8eb47c59d1dc2ca7fe80 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 29 Nov 2017 16:34:14 +0000 Subject: [PATCH 096/172] Added logging to MME GTP-C. Fixed weird comment bug. --- lib/include/srslte/asn1/gtpc_ies.h | 4 +-- lib/include/srslte/asn1/gtpc_msg.h | 1 + srsenb/enb.conf.example | 4 +-- srsepc/hdr/mme/mme.h | 4 +-- srsepc/hdr/mme/mme_gtpc.h | 11 ++++++--- srsepc/src/main.cc | 7 +++++- srsepc/src/mme/mme.cc | 6 ++--- srsepc/src/mme/mme_gtpc.cc | 39 ++++++++++++++++++++---------- srsepc/src/mme/s1ap.cc | 7 ++++-- srsepc/src/spgw/spgw.cc | 17 +++++++------ 10 files changed, 63 insertions(+), 37 deletions(-) diff --git a/lib/include/srslte/asn1/gtpc_ies.h b/lib/include/srslte/asn1/gtpc_ies.h index ab3e00d43..8c8e5d97e 100644 --- a/lib/include/srslte/asn1/gtpc_ies.h +++ b/lib/include/srslte/asn1/gtpc_ies.h @@ -402,8 +402,8 @@ enum gtpc_interface_type struct gtpc_f_teid_ie { - bool v4_present; - bool v6_present; + bool ipv4_present; + bool ipv6_present; enum gtpc_interface_type interface_type; uint32_t teid; in_addr_t ipv4; diff --git a/lib/include/srslte/asn1/gtpc_msg.h b/lib/include/srslte/asn1/gtpc_msg.h index a72e51ac9..86cf96046 100644 --- a/lib/include/srslte/asn1/gtpc_msg.h +++ b/lib/include/srslte/asn1/gtpc_msg.h @@ -248,6 +248,7 @@ struct gtpc_create_session_response bool sender_f_teid_present; struct gtpc_f_teid_ie sender_f_teid; //C //PGW S5/S8/S2b F-TEID //C + bool paa_present; struct gtpc_pdn_address_allocation_ie paa; //C //apn_restriction //apn_ambr diff --git a/srsenb/enb.conf.example b/srsenb/enb.conf.example index 44e546116..55f983c3c 100644 --- a/srsenb/enb.conf.example +++ b/srsenb/enb.conf.example @@ -22,8 +22,8 @@ phy_cell_id = 1 tac = 0x0007 mcc = 001 mnc = 01 -mme_addr = 127.0.1.100 -gtp_bind_addr = 127.0.1.1 +mme_addr = 127.0.0.1 +gtp_bind_addr = 127.0.0.1 n_prb = 25 ##################################################################### diff --git a/srsepc/hdr/mme/mme.h b/srsepc/hdr/mme/mme.h index 6016ebb75..26296c2c6 100644 --- a/srsepc/hdr/mme/mme.h +++ b/srsepc/hdr/mme/mme.h @@ -66,7 +66,7 @@ class mme: public: static mme* get_instance(void); static void cleanup(void); - int init(mme_args_t* args, srslte::log_filter *s1ap_log); + int init(mme_args_t* args, srslte::log_filter *s1ap_log, srslte::log_filter *mme_gtpc_log); void stop(); int get_s1_mme(); void run_thread(); @@ -84,7 +84,7 @@ private: /*Logs*/ srslte::log_filter *m_s1ap_log; - + srslte::log_filter *m_mme_gtpc_log; }; } // namespace srsepc diff --git a/srsepc/hdr/mme/mme_gtpc.h b/srsepc/hdr/mme/mme_gtpc.h index 3b8ed3901..17cc23189 100644 --- a/srsepc/hdr/mme/mme_gtpc.h +++ b/srsepc/hdr/mme/mme_gtpc.h @@ -26,6 +26,8 @@ #ifndef MME_GTPC_H #define MME_GTPC_H +#include "srslte/common/log.h" +#include "srslte/common/log_filter.h" #include "srslte/common/buffer_pool.h" #include #include "srslte/asn1/gtpc.h" @@ -43,9 +45,9 @@ public: static mme_gtpc* get_instance(void); static void cleanup(void); - bool init(); + bool init(srslte::log_filter *mme_gtpc_log); - uint64_t get_new_ctrl_teid(); + uint32_t get_new_ctrl_teid(); void send_create_session_request(uint64_t imsi, uint32_t mme_s1ap_id); void handle_create_session_response(srslte::gtpc_pdu *cs_resp_pdu); @@ -55,14 +57,15 @@ private: virtual ~mme_gtpc(); static mme_gtpc *m_instance; + srslte::log_filter *m_mme_gtpc_log; srslte::byte_buffer_pool *m_pool; s1ap* m_s1ap; spgw* m_spgw; in_addr_t m_mme_gtpc_ip; - uint64_t m_next_ctrl_teid; - std::map m_teid_to_mme_s1ap_id; + uint32_t m_next_ctrl_teid; + std::map m_teid_to_mme_s1ap_id; }; diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index b0a4b1432..b75fcd32d 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -201,6 +201,11 @@ main (int argc,char * argv[] ) s1ap_log.set_level(srslte::LOG_LEVEL_DEBUG); s1ap_log.set_hex_limit(32); + srslte::log_filter mme_gtpc_log; + mme_gtpc_log.init("GTPC",logger); + mme_gtpc_log.set_level(srslte::LOG_LEVEL_DEBUG); + mme_gtpc_log.set_hex_limit(32); + srslte::log_filter hss_log; hss_log.init("HSS ",logger); hss_log.set_level(srslte::LOG_LEVEL_DEBUG); @@ -212,7 +217,7 @@ main (int argc,char * argv[] ) spgw_log.set_hex_limit(32); mme *mme = mme::get_instance(); - if (mme->init(&args.mme_args, &s1ap_log)) { + if (mme->init(&args.mme_args, &s1ap_log, &mme_gtpc_log)) { cout << "Error initializing MME" << endl; exit(1); } diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index 07016b66d..ab4778c20 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -70,12 +70,12 @@ mme::cleanup(void) } int -mme::init(mme_args_t* args, srslte::log_filter *s1ap_log) +mme::init(mme_args_t* args, srslte::log_filter *s1ap_log, srslte::log_filter *mme_gtpc_log) { /*Init logger*/ m_s1ap_log = s1ap_log; - + m_mme_gtpc_log = mme_gtpc_log; /*Init S1AP*/ m_s1ap = s1ap::get_instance(); if(m_s1ap->init(args->s1ap_args, s1ap_log)){ @@ -85,7 +85,7 @@ mme::init(mme_args_t* args, srslte::log_filter *s1ap_log) /*Init GTP-C*/ m_mme_gtpc = mme_gtpc::get_instance(); - if(!m_mme_gtpc->init()) + if(!m_mme_gtpc->init(m_mme_gtpc_log)) { m_s1ap_log->console("Error initializing GTP-C\n"); exit(-1); diff --git a/srsepc/src/mme/mme_gtpc.cc b/srsepc/src/mme/mme_gtpc.cc index 7e5c87d7b..20ed20f50 100644 --- a/srsepc/src/mme/mme_gtpc.cc +++ b/srsepc/src/mme/mme_gtpc.cc @@ -36,7 +36,6 @@ mme_gtpc* mme_gtpc::m_instance = NULL; boost::mutex mme_gtpc_instance_mutex; mme_gtpc::mme_gtpc() - :m_next_ctrl_teid(1) { } @@ -66,16 +65,24 @@ mme_gtpc::cleanup(void) bool -mme_gtpc::init() +mme_gtpc::init(srslte::log_filter *mme_gtpc_log) { + + /*Init log*/ + m_mme_gtpc_log = mme_gtpc_log; + + m_next_ctrl_teid = 1; + m_s1ap = s1ap::get_instance(); m_mme_gtpc_ip = inet_addr("127.0.0.1");//FIXME At the moment, the GTP-C messages are not sent over the wire. So this parameter is not used. m_spgw = spgw::get_instance(); + m_mme_gtpc_log->info("MME GTP-C Initialized\n"); + m_mme_gtpc_log->console("MME GTP-C Initialized\n"); return true; } -uint64_t +uint32_t mme_gtpc::get_new_ctrl_teid() { return m_next_ctrl_teid++; //FIXME Use a Id pool? @@ -83,6 +90,8 @@ mme_gtpc::get_new_ctrl_teid() void mme_gtpc::send_create_session_request(uint64_t imsi, uint32_t mme_ue_s1ap_id) { + m_mme_gtpc_log->info("Preparing Create Session Request. IMSI %lu\n", imsi); + m_mme_gtpc_log->console("Preparing Create Session Request. IMSI %lu\n", imsi); struct srslte::gtpc_pdu cs_req_pdu; struct srslte::gtpc_create_session_request *cs_req = &cs_req_pdu.choice.create_session_request; @@ -99,19 +108,22 @@ mme_gtpc::send_create_session_request(uint64_t imsi, uint32_t mme_ue_s1ap_id) cs_req_pdu.header.type = srslte::GTPC_MSG_TYPE_CREATE_SESSION_REQUEST; //Setup GTP-C Create Session Request IEs - // Control TEID allocated \\ + // Control TEID allocated cs_req->sender_f_teid.teid = get_new_ctrl_teid(); cs_req->sender_f_teid.ipv4 = m_mme_gtpc_ip; - // APN \\ + + m_mme_gtpc_log->info("Next control TEID: %lu \n", m_next_ctrl_teid); + m_mme_gtpc_log->info("Allocated control TEID: %lu \n", cs_req->sender_f_teid.teid); + m_mme_gtpc_log->console("Allocated control TEID: %lu \n", cs_req->sender_f_teid.teid); + // APN memcpy(cs_req->apn, "internet", sizeof("internet")); - // RAT Type \\ - cs_req->rat_type = GTPC_RAT_TYPE::EUTRAN; + // RAT Type + //cs_req->rat_type = srslte::GTPC_RAT_TYPE::EUTRAN; //Save RX Control TEID - m_teid_to_mme_s1ap_id.insert(std::pair(cs_req->sender_f_teid.teid, mme_ue_s1ap_id)); + m_teid_to_mme_s1ap_id.insert(std::pair(cs_req->sender_f_teid.teid, mme_ue_s1ap_id)); m_spgw->handle_create_session_request(cs_req, &cs_resp_pdu); - handle_create_session_response(&cs_resp_pdu); } @@ -119,24 +131,25 @@ void mme_gtpc::handle_create_session_response(srslte::gtpc_pdu *cs_resp_pdu) { struct srslte::gtpc_create_session_response *cs_resp = & cs_resp_pdu->choice.create_session_response; - + m_mme_gtpc_log->info("Received Create Session Response\n"); if (cs_resp_pdu->header.type != srslte::GTPC_MSG_TYPE_CREATE_SESSION_RESPONSE) { - //m_mme_gtpc_log->warning("Could not create GTPC session.\n"); + m_mme_gtpc_log->warning("Could not create GTPC session. Not a create session response\n"); //TODO Handle err return; } if (cs_resp->cause.cause_value != srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED){ - //m_mme_gtpc_log->warning("Could not create GTPC session.\n"); + m_mme_gtpc_log->warning("Could not create GTPC session. Create Session Request not accepted\n"); //TODO Handle error return; } //Get MME_UE_S1AP_ID from the Ctrl TEID - std::map::iterator id_it = m_teid_to_mme_s1ap_id.find(cs_resp_pdu->header.teid); + std::map::iterator id_it = m_teid_to_mme_s1ap_id.find(cs_resp_pdu->header.teid); if(id_it == m_teid_to_mme_s1ap_id.end()) { //Could not find MME UE S1AP TEID + m_mme_gtpc_log->warning("Could not find MME UE S1AP TEID.\n"); return; } uint32_t mme_s1ap_id = id_it->second; diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index b4064efd6..b562a09cf 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -428,7 +428,7 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT m_s1ap_log->warning("Could not find UE. MME-UE S1AP id: %lu\n",mme_ue_s1ap_id); return false; } - m_s1ap_log->debug("Found UE. MME-UE S1AP id: %lu",mme_ue_s1ap_id); + m_s1ap_log->debug("Found UE. MME-UE S1AP id: %lu\n",mme_ue_s1ap_id); //Get NAS message type uint8_t pd, msg_type; @@ -564,6 +564,8 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT *erab_ctxt = &in_ctxt_req->E_RABToBeSetupListCtxtSUReq.buffer[0]; //FIXME support more than one erab srslte::byte_buffer_t *reply_buffer = m_pool->allocate(); + m_s1ap_log->info("Preparing to send Initial Context Setup request\n"); + //Find UE Context std::map::iterator ue_ctx_it = m_active_ues.find(mme_ue_s1ap_id); if(ue_ctx_it == m_active_ues.end()) @@ -622,7 +624,8 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: m_s1ap_log->error("Failed to send Initial Context Setup Request\n"); return false; } - + m_s1ap_log->info("Sent Intial Context Setup Request\n"); + m_s1ap_log->console("Sent Intial Context Setup Request\n"); m_pool->deallocate(reply_buffer); return true; diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index a9e833b18..cf53686a1 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -313,13 +313,14 @@ spgw::handle_create_session_request(struct srslte::gtpc_create_session_request * srslte::gtpc_header *header = &cs_resp_pdu->header; srslte::gtpc_create_session_response *cs_resp = &cs_resp_pdu->choice.create_session_response; + + m_spgw_log->info("Received Create Session Request\n"); //Setup GTP-C header header->piggyback = false; header->teid_present = true; header->teid = cs_req->sender_f_teid.teid; //Send create session requesponse to the CS Request TEID header->type = srslte::GTPC_MSG_TYPE_CREATE_SESSION_RESPONSE; - //Setup uplink control TEID uint64_t spgw_uplink_ctrl_teid = get_new_ctrl_teid(); //Setup uplink user TEID @@ -327,28 +328,28 @@ spgw::handle_create_session_request(struct srslte::gtpc_create_session_request * //Allocate UE IP in_addr_t ue_ip = get_new_ue_ipv4(); - //Save the UE IMSI to Ctrl TEID map //TODO!!! + //Save the UE IP to User TEID map //TODO!!! //Create session response message //Initialize to zero\\ bzero(cs_resp,sizeof(struct srslte::gtpc_create_session_response)); - //Setup Cause\\ + //Setup Cause cs_resp->cause.cause_value = srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED; - //Setup sender F-TEID (ctrl)\\ - cs_resp->sender_f_teid.teid_present = true; + //Setup sender F-TEID (ctrl) + cs_resp->sender_f_teid.ipv4_present = true; cs_resp->sender_f_teid.teid = spgw_uplink_ctrl_teid; cs_resp->sender_f_teid.ipv4 = 0;//FIXME This is not relevant, as the GTP-C is not transmitted over sockets yet. - //Bearer context created\\ + //Bearer context created cs_resp->eps_bearer_context_created.ebi = 5; cs_resp->eps_bearer_context_created.cause.cause_value = srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED; cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid_present=true; cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.teid = spgw_uplink_user_teid; - //Fill in the PDA\\ + //Fill in the PDA cs_resp->paa_present = true; cs_resp->paa.pdn_type = srslte::GTPC_PDN_TYPE_IPV4; cs_resp->paa.ipv4_present = true; cs_resp->paa.ipv4 = ue_ip; - + m_spgw_log->info("Sending Create Session Response\n"); m_mme_gtpc->handle_create_session_response(cs_resp_pdu); return; } From d9bb3bbf4e1afe6ae150d1dff1fb0709fe960b7c Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 29 Nov 2017 18:35:02 +0000 Subject: [PATCH 097/172] eNB receiving Initial Context Setup, but segfaulting. Probably because QoS structure missing. --- srsepc/src/mme/s1ap.cc | 41 +++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index b562a09cf..8f8f9da6e 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -366,7 +366,7 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini m_s1ap_log->console("EPS Bearer id: %d\n", eps_bearer_id); //Add eNB info to UE ctxt - memcpy(&ue_ctx.enb_sri, &enb_sri, sizeof(struct sctp_sndrcvinfo)); + memcpy(&ue_ctx.enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); //Get Authentication Vectors from HSS if(!m_hss->gen_auth_info_answer_milenage(imsi, ue_ctx.security_ctxt.k_asme, autn, rand, ue_ctx.security_ctxt.xres)) @@ -554,6 +554,7 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: //Prepare reply PDU LIBLTE_S1AP_S1AP_PDU_STRUCT pdu; + bzero(&pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE; LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *init = &pdu.choice.initiatingMessage; @@ -561,6 +562,7 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_INITIALCONTEXTSETUPREQUEST; LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT *in_ctxt_req = &init->choice.InitialContextSetupRequest; + LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT *erab_ctxt = &in_ctxt_req->E_RABToBeSetupListCtxtSUReq.buffer[0]; //FIXME support more than one erab srslte::byte_buffer_t *reply_buffer = m_pool->allocate(); @@ -576,7 +578,6 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: ue_ctx = ue_ctx_it->second; //Add MME and eNB S1AP Ids - bzero(&in_ctxt_req, sizeof(in_ctxt_req)); in_ctxt_req->MME_UE_S1AP_ID.MME_UE_S1AP_ID = ue_ctx->mme_ue_s1ap_id; in_ctxt_req->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ue_ctx->enb_ue_s1ap_id; @@ -584,14 +585,41 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL.BitRate=4294967295;//2^32-1 in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL.BitRate=4294967295;//FIXME Get UE-AMBR from HSS - //eRAB context to setup + /* + typedef struct{ + bool ext; + LIBLTE_S1AP_E_RAB_ID_STRUCT e_RAB_ID; + LIBLTE_S1AP_E_RABLEVELQOSPARAMETERS_STRUCT e_RABlevelQoSParameters; + LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT transportLayerAddress; + LIBLTE_S1AP_GTP_TEID_STRUCT gTP_TEID; + LIBLTE_S1AP_NAS_PDU_STRUCT nAS_PDU; + bool nAS_PDU_present; + LIBLTE_S1AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; + bool iE_Extensions_present; + }LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT; + */ + /* + typedef struct{ + bool ext; + LIBLTE_S1AP_QCI_STRUCT qCI; + LIBLTE_S1AP_ALLOCATIONANDRETENTIONPRIORITY_STRUCT allocationRetentionPriority; + LIBLTE_S1AP_GBR_QOSINFORMATION_STRUCT gbrQosInformation; + bool gbrQosInformation_present; + LIBLTE_S1AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; + bool iE_Extensions_present; + }LIBLTE_S1AP_E_RABLEVELQOSPARAMETERS_STRUCT; + */ + //Setup eRAB context + in_ctxt_req->E_RABToBeSetupListCtxtSUReq.len = 1; erab_ctxt->e_RAB_ID.E_RAB_ID = cs_resp->eps_bearer_context_created.ebi; + //Setup E-RAB QoS parameters + + //Set E-RAB S-GW F-TEID if (cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid_present == false){ m_s1ap_log->error("Did not receive S1-U TEID in create session response\n"); return false; - } - - //Set S-GW F-TEID + } + erab_ctxt->transportLayerAddress.n_bits = 32; //IPv4 uint32_t sgw_s1u_ip = cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.ipv4; uint8_t *tmp_ptr = erab_ctxt->transportLayerAddress.buffer; liblte_value_2_bits(sgw_s1u_ip, &tmp_ptr, 32);//FIXME consider ipv6 @@ -612,6 +640,7 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: LIBLTE_ERROR_ENUM err = liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)reply_buffer); + //reply_buffer->N_bytes = pdu->NAS_PDU.n_octets; if(err != LIBLTE_SUCCESS) { m_s1ap_log->error("Could not pack Initial Context Setup Request Message\n"); From 6fea4339cd6f0a54151030c64bb674c67e90604b Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 30 Nov 2017 11:21:56 +0000 Subject: [PATCH 098/172] Adding E-RAB QoS info --- srsepc/src/mme/s1ap.cc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 8f8f9da6e..c10ff8197 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -608,12 +608,26 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: LIBLTE_S1AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; bool iE_Extensions_present; }LIBLTE_S1AP_E_RABLEVELQOSPARAMETERS_STRUCT; + + typedef struct{ + bool ext; + LIBLTE_S1AP_PRIORITYLEVEL_STRUCT priorityLevel; + LIBLTE_S1AP_PRE_EMPTIONCAPABILITY_ENUM pre_emptionCapability; + LIBLTE_S1AP_PRE_EMPTIONVULNERABILITY_ENUM pre_emptionVulnerability; + LIBLTE_S1AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; + bool iE_Extensions_present; + }LIBLTE_S1AP_ALLOCATIONANDRETENTIONPRIORITY_STRUCT; */ //Setup eRAB context in_ctxt_req->E_RABToBeSetupListCtxtSUReq.len = 1; erab_ctxt->e_RAB_ID.E_RAB_ID = cs_resp->eps_bearer_context_created.ebi; //Setup E-RAB QoS parameters + erab_ctxt->e_RABlevelQoSParameters.qCI.QCI = 9; + erab_ctxt->e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel.PriorityLevel = 15 //Lowest + erab_ctxt->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability = LIBLTE_S1AP_PRE_EMPTIONCAPABILITY_SHALL_NOT_TRIGGER_PRE_EMPTION; + erab_ctxt->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability = LIBLTE_S1AP_PRE_EMPTIONVULNERABILITY_PRE_EMPTABLE; + erab_ctxt->e_RABlevelQoSParameter.gbrQosInformation_present=false; //Set E-RAB S-GW F-TEID if (cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid_present == false){ m_s1ap_log->error("Did not receive S1-U TEID in create session response\n"); From bdd85d4f2d123007514fbe00d63d8a3e2fa2af97 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 30 Nov 2017 11:22:49 +0000 Subject: [PATCH 099/172] Commit for Justin --- srsepc/src/mme/s1ap.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index c10ff8197..70eb247b0 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -661,12 +661,14 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: return false; } //Send Reply to eNB + /* ssize_t n_sent = sctp_send(m_s1mme,reply_buffer->msg, reply_buffer->N_bytes, &ue_ctx->enb_sri, 0); if(n_sent == -1) { m_s1ap_log->error("Failed to send Initial Context Setup Request\n"); return false; } + */ m_s1ap_log->info("Sent Intial Context Setup Request\n"); m_s1ap_log->console("Sent Intial Context Setup Request\n"); From 579d73165ab299f8d1d197bddf1fab59be9328a0 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 30 Nov 2017 11:25:45 +0000 Subject: [PATCH 100/172] Commit for Justin 2. --- srsepc/src/mme/s1ap.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 70eb247b0..868c67972 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -622,12 +622,13 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: in_ctxt_req->E_RABToBeSetupListCtxtSUReq.len = 1; erab_ctxt->e_RAB_ID.E_RAB_ID = cs_resp->eps_bearer_context_created.ebi; //Setup E-RAB QoS parameters - erab_ctxt->e_RABlevelQoSParameters.qCI.QCI = 9; + /*erab_ctxt->e_RABlevelQoSParameters.qCI.QCI = 9; erab_ctxt->e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel.PriorityLevel = 15 //Lowest erab_ctxt->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability = LIBLTE_S1AP_PRE_EMPTIONCAPABILITY_SHALL_NOT_TRIGGER_PRE_EMPTION; erab_ctxt->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability = LIBLTE_S1AP_PRE_EMPTIONVULNERABILITY_PRE_EMPTABLE; erab_ctxt->e_RABlevelQoSParameter.gbrQosInformation_present=false; + */ //Set E-RAB S-GW F-TEID if (cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid_present == false){ m_s1ap_log->error("Did not receive S1-U TEID in create session response\n"); @@ -661,14 +662,14 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: return false; } //Send Reply to eNB - /* + ssize_t n_sent = sctp_send(m_s1mme,reply_buffer->msg, reply_buffer->N_bytes, &ue_ctx->enb_sri, 0); if(n_sent == -1) { m_s1ap_log->error("Failed to send Initial Context Setup Request\n"); return false; } - */ + m_s1ap_log->info("Sent Intial Context Setup Request\n"); m_s1ap_log->console("Sent Intial Context Setup Request\n"); From 1a4868ebafe34c483ef622493e2d3b394c4292eb Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 30 Nov 2017 11:47:34 +0000 Subject: [PATCH 101/172] Justin 3 --- srsepc/src/mme/s1ap.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 868c67972..17e9f310b 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -662,14 +662,14 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: return false; } //Send Reply to eNB - + /* ssize_t n_sent = sctp_send(m_s1mme,reply_buffer->msg, reply_buffer->N_bytes, &ue_ctx->enb_sri, 0); if(n_sent == -1) { m_s1ap_log->error("Failed to send Initial Context Setup Request\n"); return false; } - + */ m_s1ap_log->info("Sent Intial Context Setup Request\n"); m_s1ap_log->console("Sent Intial Context Setup Request\n"); From 45ca57b4b600b6a10da58edecad7f101fa0d801d Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 30 Nov 2017 12:12:18 +0000 Subject: [PATCH 102/172] eNB receiving Initial Context setup request correctly (without NAS attach accept and activate default bearer) --- srsepc/src/mme/s1ap.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 17e9f310b..a3d9dbf22 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -622,13 +622,13 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: in_ctxt_req->E_RABToBeSetupListCtxtSUReq.len = 1; erab_ctxt->e_RAB_ID.E_RAB_ID = cs_resp->eps_bearer_context_created.ebi; //Setup E-RAB QoS parameters - /*erab_ctxt->e_RABlevelQoSParameters.qCI.QCI = 9; - erab_ctxt->e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel.PriorityLevel = 15 //Lowest + erab_ctxt->e_RABlevelQoSParameters.qCI.QCI = 9; + erab_ctxt->e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel.PriorityLevel = 15 ;//Lowest erab_ctxt->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability = LIBLTE_S1AP_PRE_EMPTIONCAPABILITY_SHALL_NOT_TRIGGER_PRE_EMPTION; erab_ctxt->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability = LIBLTE_S1AP_PRE_EMPTIONVULNERABILITY_PRE_EMPTABLE; - erab_ctxt->e_RABlevelQoSParameter.gbrQosInformation_present=false; - */ + erab_ctxt->e_RABlevelQoSParameters.gbrQosInformation_present=false; + //Set E-RAB S-GW F-TEID if (cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid_present == false){ m_s1ap_log->error("Did not receive S1-U TEID in create session response\n"); @@ -650,7 +650,7 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: liblte_security_generate_k_enb(ue_ctx->security_ctxt.k_asme, ue_ctx->security_ctxt.dl_nas_count, key_enb); liblte_unpack(key_enb, 32, in_ctxt_req->SecurityKey.buffer); - //Set Attach accepted and activate defaulte bearer NAS messages + //Set Attach accepted and activat default bearer NAS messages //TODO @@ -662,14 +662,14 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: return false; } //Send Reply to eNB - /* + ssize_t n_sent = sctp_send(m_s1mme,reply_buffer->msg, reply_buffer->N_bytes, &ue_ctx->enb_sri, 0); if(n_sent == -1) { m_s1ap_log->error("Failed to send Initial Context Setup Request\n"); return false; } - */ + m_s1ap_log->info("Sent Intial Context Setup Request\n"); m_s1ap_log->console("Sent Intial Context Setup Request\n"); From f71c87d895912c786114d72dfe4509c2afe17d2f Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 30 Nov 2017 17:06:56 +0000 Subject: [PATCH 103/172] Starting to add attach accept and activate default bearer request NAS messages. --- lib/include/srslte/asn1/gtpc.h | 3 -- lib/include/srslte/asn1/gtpc_ies.h | 4 +- srsepc/hdr/mme/s1ap_common.h | 2 + srsepc/hdr/mme/s1ap_nas_transport.h | 2 + srsepc/src/mme/s1ap.cc | 65 +++++++++++--------------- srsepc/src/mme/s1ap_nas_transport.cc | 69 +++++++++++++++++++++++++--- srsepc/src/spgw/spgw.cc | 2 +- 7 files changed, 95 insertions(+), 52 deletions(-) diff --git a/lib/include/srslte/asn1/gtpc.h b/lib/include/srslte/asn1/gtpc.h index 8fdbab53d..e670333bf 100644 --- a/lib/include/srslte/asn1/gtpc.h +++ b/lib/include/srslte/asn1/gtpc.h @@ -27,9 +27,6 @@ #include #include "srslte/asn1/gtpc_msg.h" -//Helpful marcos to convert TEIDs (uint64_t) to/from network byte order -#define HTONLL(x) ((1==htonl(1)) ? (x) : (((uint64_t)htonl((x) & 0xFFFFFFFFUL)) << 32) | htonl((uint32_t)((x) >> 32))) -#define NTOHLL(x) ((1==ntohl(1)) ? (x) : (((uint64_t)ntohl((x) & 0xFFFFFFFFUL)) << 32) | ntohl((uint32_t)((x) >> 32))) namespace srslte{ diff --git a/lib/include/srslte/asn1/gtpc_ies.h b/lib/include/srslte/asn1/gtpc_ies.h index 8c8e5d97e..35b5e6498 100644 --- a/lib/include/srslte/asn1/gtpc_ies.h +++ b/lib/include/srslte/asn1/gtpc_ies.h @@ -310,7 +310,7 @@ struct gtpc_ambr_ie /**************************************************************************** * - * GTP-C PAA Type IE + * GTP-C PDN Type IE * Ref: 3GPP TS 29.274 v10.14.0 Figure 8.14-1 * ***************************************************************************/ @@ -327,7 +327,7 @@ struct gtpc_pdn_address_allocation_ie bool ipv4_present; bool ipv6_present; in_addr_t ipv4; - struct in6_addr; + struct in6_addr ipv6; }; //TODO diff --git a/srsepc/hdr/mme/s1ap_common.h b/srsepc/hdr/mme/s1ap_common.h index a3ac54dab..ad004190d 100644 --- a/srsepc/hdr/mme/s1ap_common.h +++ b/srsepc/hdr/mme/s1ap_common.h @@ -65,6 +65,8 @@ typedef struct{ uint32_t ul_nas_count; srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo; srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo; + uint8_t k_nas_enc[32]; + uint8_t k_nas_int[32]; } security_ctxt; } ue_ctx_t; }//namespace diff --git a/srsepc/hdr/mme/s1ap_nas_transport.h b/srsepc/hdr/mme/s1ap_nas_transport.h index f4e207ce6..feb11379f 100644 --- a/srsepc/hdr/mme/s1ap_nas_transport.h +++ b/srsepc/hdr/mme/s1ap_nas_transport.h @@ -29,6 +29,7 @@ #include "srslte/asn1/liblte_s1ap.h" #include "srslte/common/buffer_pool.h" #include "mme/s1ap_common.h" +#include "srslte/asn1/gtpc.h" namespace srsepc{ @@ -45,6 +46,7 @@ public: bool unpack_authentication_response(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT *auth_resp); bool pack_security_mode_command(srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx); + bool pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT *erab_ctxt, struct srslte::gtpc_pdn_address_allocation_ie *paa, srslte::byte_buffer_t *nas_buffer); void log_unhandled_attach_request_ies(const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req); void log_unhandled_pdn_con_request_ies(const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req); diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index a3d9dbf22..0544b5311 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -585,39 +585,6 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL.BitRate=4294967295;//2^32-1 in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL.BitRate=4294967295;//FIXME Get UE-AMBR from HSS - /* - typedef struct{ - bool ext; - LIBLTE_S1AP_E_RAB_ID_STRUCT e_RAB_ID; - LIBLTE_S1AP_E_RABLEVELQOSPARAMETERS_STRUCT e_RABlevelQoSParameters; - LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT transportLayerAddress; - LIBLTE_S1AP_GTP_TEID_STRUCT gTP_TEID; - LIBLTE_S1AP_NAS_PDU_STRUCT nAS_PDU; - bool nAS_PDU_present; - LIBLTE_S1AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; - bool iE_Extensions_present; - }LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT; - */ - /* - typedef struct{ - bool ext; - LIBLTE_S1AP_QCI_STRUCT qCI; - LIBLTE_S1AP_ALLOCATIONANDRETENTIONPRIORITY_STRUCT allocationRetentionPriority; - LIBLTE_S1AP_GBR_QOSINFORMATION_STRUCT gbrQosInformation; - bool gbrQosInformation_present; - LIBLTE_S1AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; - bool iE_Extensions_present; - }LIBLTE_S1AP_E_RABLEVELQOSPARAMETERS_STRUCT; - - typedef struct{ - bool ext; - LIBLTE_S1AP_PRIORITYLEVEL_STRUCT priorityLevel; - LIBLTE_S1AP_PRE_EMPTIONCAPABILITY_ENUM pre_emptionCapability; - LIBLTE_S1AP_PRE_EMPTIONVULNERABILITY_ENUM pre_emptionVulnerability; - LIBLTE_S1AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; - bool iE_Extensions_present; - }LIBLTE_S1AP_ALLOCATIONANDRETENTIONPRIORITY_STRUCT; - */ //Setup eRAB context in_ctxt_req->E_RABToBeSetupListCtxtSUReq.len = 1; erab_ctxt->e_RAB_ID.E_RAB_ID = cs_resp->eps_bearer_context_created.ebi; @@ -651,8 +618,18 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: liblte_unpack(key_enb, 32, in_ctxt_req->SecurityKey.buffer); //Set Attach accepted and activat default bearer NAS messages - //TODO - + if(cs_resp->paa_present != true) + { + m_s1ap_log->error("PAA not present\n"); + return false; + } + if(cs_resp->paa.pdn_type != srslte::GTPC_PDN_TYPE_IPV4) + { + m_s1ap_log->error("IPv6 not supported yet\n"); + return false; + } + srslte::byte_buffer_t *nas_buffer = m_pool->allocate(); + m_s1ap_nas_transport.pack_attach_accept(ue_ctx, erab_ctxt, &cs_resp->paa, nas_buffer); LIBLTE_ERROR_ENUM err = liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)reply_buffer); //reply_buffer->N_bytes = pdu->NAS_PDU.n_octets; @@ -674,13 +651,23 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: m_s1ap_log->console("Sent Intial Context Setup Request\n"); m_pool->deallocate(reply_buffer); + m_pool->deallocate(nas_buffer); return true; } - bool - s1ap::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri) - { - uint32_t mme_ue_s1ap_id = ue_rel->MME_UE_S1AP_ID.MME_UE_S1AP_ID; + /* +bool +s1ap::handle_initial_context_setup_response(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp) +{ + return true; +} + */ + +bool +s1ap::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri) +{ + + uint32_t mme_ue_s1ap_id = ue_rel->MME_UE_S1AP_ID.MME_UE_S1AP_ID; m_s1ap_log->info("Received UE Context Release Request. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); m_s1ap_log->console("Received UE Context Release Request. MME-UE S1AP Id %d\n", mme_ue_s1ap_id); diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 62828d9f6..a9772b4fe 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -290,17 +290,14 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, //TODO which is the RB ID? Standard says a constant, but which? uint8_t mac[4]; - uint8_t k_nas_enc[32]; - uint8_t k_nas_int[32]; - srslte::security_generate_k_nas( ue_ctx->security_ctxt.k_asme, srslte::CIPHERING_ALGORITHM_ID_EEA0, srslte::INTEGRITY_ALGORITHM_ID_128_EIA1, - k_nas_enc, - k_nas_int + ue_ctx->security_ctxt.k_nas_enc, + ue_ctx->security_ctxt.k_nas_int ); - srslte::security_128_eia1 (&k_nas_int[16], + srslte::security_128_eia1 (&ue_ctx->security_ctxt.k_nas_int[16], count, 0, SECURITY_DIRECTION_DOWNLINK, @@ -429,7 +426,7 @@ s1ap_nas_transport::log_unhandled_initial_ue_message_ies(LIBLTE_S1AP_MESSAGE_INI } if(init_ue->CellAccessMode_present){ m_s1ap_log->warning("Cell Access Mode present, but not handled."); - } + } if(init_ue->GW_TransportLayerAddress_present){ m_s1ap_log->warning("GW Transport Layer present, but not handled."); } @@ -455,6 +452,64 @@ s1ap_nas_transport::log_unhandled_initial_ue_message_ies(LIBLTE_S1AP_MESSAGE_INI } +bool +s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT *erab_ctxt, struct srslte::gtpc_pdn_address_allocation_ie *paa, srslte::byte_buffer_t *nas_buffer) { + LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT attach_accept; + LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT act_def_eps_bearer_context_req; + m_s1ap_log->info("Packing Attach Accept\n"); + bzero(&attach_accept, sizeof(LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT)); + bzero(&act_def_eps_bearer_context_req, sizeof(LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT)); + + //Attach accept + attach_accept.eps_attach_result = LIBLTE_MME_EPS_ATTACH_RESULT_EPS_ONLY; + //Mandatory + //FIXME: Set t3412.unit + //FIXME: Set tai_list + //FIXME: Set esm_msg + act_def_eps_bearer_context_req.pdn_addr.pdn_type = LIBLTE_MME_PDN_TYPE_IPV4; + memcpy(act_def_eps_bearer_context_req.pdn_addr.addr, &paa->ipv4, 4); + /* + act_def_eps_bearer_context_req.pdn_addr.addr[0] |= ip_addr << 24; + act_def_eps_bearer_context_req.pdn_addr.addr[1] |= ip_addr << 16; + act_def_eps_bearer_context_req.pdn_addr.addr[2] |= ip_addr << 8; + act_def_eps_bearer_context_req.pdn_addr.addr[3] |= ip_addr; + */ + //Activate default EPS bearer context + act_def_eps_bearer_context_req.eps_bearer_id = erab_ctxt->e_RAB_ID.E_RAB_ID; + act_def_eps_bearer_context_req.transaction_id_present = false; + liblte_mme_pack_activate_default_eps_bearer_context_request_msg(&act_def_eps_bearer_context_req, &attach_accept.esm_msg); + + //FIXME: Set the following parameters +// act_def_eps_bearer_context_req.eps_qos.qci +// act_def_eps_bearer_context_req.eps_qos.br_present +// act_def_eps_bearer_context_req.eps_qos.br_ext_present +// act_def_eps_bearer_context_req.apn.apn +// act_def_eps_bearer_context_req.negotiated_qos_present +// act_def_eps_bearer_context_req.llc_sapi_present +// act_def_eps_bearer_context_req.radio_prio_present +// act_def_eps_bearer_context_req.packet_flow_id_present +// act_def_eps_bearer_context_req.apn_ambr_present +// act_def_eps_bearer_context_req.protocol_cnfg_opts_present +// act_def_eps_bearer_context_req.connectivity_type_present + + // FIXME: Setup the default EPS bearer context + + //Integrity protect NAS message + uint8_t mac[4]; + srslte::security_128_eia1 (&ue_ctx->security_ctxt.k_nas_int[16], + ue_ctx->security_ctxt.dl_nas_count, + 0, + SECURITY_DIRECTION_DOWNLINK, + &nas_buffer->msg[5], + nas_buffer->N_bytes - 5, + mac + ); + + memcpy(&nas_buffer->msg[1],mac,4); + m_s1ap_log->info("Packed Attach Complete\n"); + + return true; +} } //namespace srsepc diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index cf53686a1..19c206f6e 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -344,7 +344,7 @@ spgw::handle_create_session_request(struct srslte::gtpc_create_session_request * cs_resp->eps_bearer_context_created.cause.cause_value = srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED; cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid_present=true; cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.teid = spgw_uplink_user_teid; - //Fill in the PDA + //Fill in the PAA cs_resp->paa_present = true; cs_resp->paa.pdn_type = srslte::GTPC_PDN_TYPE_IPV4; cs_resp->paa.ipv4_present = true; From 45434351cc7ece5571644ef8b34270dec4ce6c5b Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 30 Nov 2017 18:42:30 +0000 Subject: [PATCH 104/172] Continuing to add attach accept and activate default bearer request NAS messages. --- srsepc/src/mme/s1ap_nas_transport.cc | 72 ++++++++++++++++++---------- 1 file changed, 46 insertions(+), 26 deletions(-) diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index a9772b4fe..7a59bd5c1 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -464,37 +464,57 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE //Attach accept attach_accept.eps_attach_result = LIBLTE_MME_EPS_ATTACH_RESULT_EPS_ONLY; //Mandatory - //FIXME: Set t3412.unit - //FIXME: Set tai_list - //FIXME: Set esm_msg + //FIXME: Set t3412 from config + attach_accept.t3412.unit = LIBLTE_MME_GPRS_TIMER_DEACTIVATED; // 111 -> Timer deactivated + attach_accept.t3412.unit = 0; // No periodic tracking update + //FIXME: Set tai_list from config + attach_accept.tai_list.N_tais = 1; + attach_accept.tai_list.tai[0].mcc = 1; + attach_accept.tai_list.tai[0].mnc = 1; + attach_accept.tai_list.tai[0].tac = 1; + + //Set activate default eps bearer (esm_ms) + //Set pdn_addr act_def_eps_bearer_context_req.pdn_addr.pdn_type = LIBLTE_MME_PDN_TYPE_IPV4; memcpy(act_def_eps_bearer_context_req.pdn_addr.addr, &paa->ipv4, 4); - /* - act_def_eps_bearer_context_req.pdn_addr.addr[0] |= ip_addr << 24; - act_def_eps_bearer_context_req.pdn_addr.addr[1] |= ip_addr << 16; - act_def_eps_bearer_context_req.pdn_addr.addr[2] |= ip_addr << 8; - act_def_eps_bearer_context_req.pdn_addr.addr[3] |= ip_addr; - */ - //Activate default EPS bearer context + //Set eps bearer id act_def_eps_bearer_context_req.eps_bearer_id = erab_ctxt->e_RAB_ID.E_RAB_ID; act_def_eps_bearer_context_req.transaction_id_present = false; + //set eps_qos + act_def_eps_bearer_context_req.eps_qos.qci = erab_ctxt->e_RABlevelQoSParameters.qCI.QCI; + act_def_eps_bearer_context_req.eps_qos.mbr_ul = 254; //FIXME + act_def_eps_bearer_context_req.eps_qos.mbr_dl = 254; //FIXME + act_def_eps_bearer_context_req.eps_qos.mbr_ul_ext = 250; //FIXME + act_def_eps_bearer_context_req.eps_qos.mbr_dl_ext = 250; //FIXME check + //set apn + //act_def_eps_bearer_context_req.apn + std::string apn("internet"); + act_def_eps_bearer_context_req.apn.apn = apn; //FIXME + + /* + typedef struct{ + LIBLTE_MME_EPS_QUALITY_OF_SERVICE_STRUCT eps_qos; //TODO + LIBLTE_MME_ACCESS_POINT_NAME_STRUCT apn; //TODO + LIBLTE_MME_PDN_ADDRESS_STRUCT pdn_addr; //DONE + uint8 eps_bearer_id; //DONE + uint8 proc_transaction_id; +}LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT; + typedef struct{ + uint8 qci; + uint8 mbr_ul; + uint8 mbr_dl; + uint8 gbr_ul; + uint8 gbr_dl; + uint8 mbr_ul_ext; + uint8 mbr_dl_ext; + uint8 gbr_ul_ext; + uint8 gbr_dl_ext; + bool br_present; + bool br_ext_present; + }LIBLTE_MME_EPS_QUALITY_OF_SERVICE_STRUCT; + */ + liblte_mme_pack_activate_default_eps_bearer_context_request_msg(&act_def_eps_bearer_context_req, &attach_accept.esm_msg); - - //FIXME: Set the following parameters -// act_def_eps_bearer_context_req.eps_qos.qci -// act_def_eps_bearer_context_req.eps_qos.br_present -// act_def_eps_bearer_context_req.eps_qos.br_ext_present -// act_def_eps_bearer_context_req.apn.apn -// act_def_eps_bearer_context_req.negotiated_qos_present -// act_def_eps_bearer_context_req.llc_sapi_present -// act_def_eps_bearer_context_req.radio_prio_present -// act_def_eps_bearer_context_req.packet_flow_id_present -// act_def_eps_bearer_context_req.apn_ambr_present -// act_def_eps_bearer_context_req.protocol_cnfg_opts_present -// act_def_eps_bearer_context_req.connectivity_type_present - - // FIXME: Setup the default EPS bearer context - //Integrity protect NAS message uint8_t mac[4]; srslte::security_128_eia1 (&ue_ctx->security_ctxt.k_nas_int[16], From c05c328194fb16ebea28ffdd58def62f0236e121 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 30 Nov 2017 20:08:37 +0000 Subject: [PATCH 105/172] UE receives attach accepted ok and gets an IP. Still need to parse the initial context setup complete and modify the bearer request and setup the GTPU tunnels. --- srsepc/src/mme/s1ap_nas_transport.cc | 40 +++++++++++++++++++++------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 7a59bd5c1..835241397 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -276,9 +276,9 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, sm_cmd.nonce_mme_present=false; uint8_t sec_hdr_type=3; - uint32_t count=0; - - LIBLTE_ERROR_ENUM err = liblte_mme_pack_security_mode_command_msg(&sm_cmd,sec_hdr_type, count,(LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + + ue_ctx->security_ctxt.dl_nas_count = 0; + LIBLTE_ERROR_ENUM err = liblte_mme_pack_security_mode_command_msg(&sm_cmd,sec_hdr_type, ue_ctx->security_ctxt.dl_nas_count,(LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); if(err != LIBLTE_SUCCESS) { m_s1ap_log->console("Error packing Athentication Request\n"); @@ -298,7 +298,7 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, ); srslte::security_128_eia1 (&ue_ctx->security_ctxt.k_nas_int[16], - count, + ue_ctx->security_ctxt.dl_nas_count, 0, SECURITY_DIRECTION_DOWNLINK, &nas_buffer->msg[5], @@ -318,9 +318,8 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, m_s1ap_log->console("Error packing Athentication Request\n"); return false; } - - m_pool->deallocate(nas_buffer); + m_pool->deallocate(nas_buffer); return true; } @@ -456,10 +455,9 @@ bool s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT *erab_ctxt, struct srslte::gtpc_pdn_address_allocation_ie *paa, srslte::byte_buffer_t *nas_buffer) { LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT attach_accept; LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT act_def_eps_bearer_context_req; + bzero(&act_def_eps_bearer_context_req,sizeof(LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT)); m_s1ap_log->info("Packing Attach Accept\n"); - bzero(&attach_accept, sizeof(LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT)); - bzero(&act_def_eps_bearer_context_req, sizeof(LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT)); //Attach accept attach_accept.eps_attach_result = LIBLTE_MME_EPS_ATTACH_RESULT_EPS_ONLY; @@ -473,6 +471,19 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE attach_accept.tai_list.tai[0].mnc = 1; attach_accept.tai_list.tai[0].tac = 1; + //Make sure all unused options are set to false + attach_accept.guti_present=false; + attach_accept.lai_present=false; + attach_accept.ms_id_present=false; + attach_accept.emm_cause_present=false; + attach_accept.t3402_present=false; + attach_accept.t3423_present=false; + attach_accept.equivalent_plmns_present=false; + attach_accept.emerg_num_list_present=false; + attach_accept.eps_network_feature_support_present=false; + attach_accept.additional_update_result_present=false; + attach_accept.t3412_ext_present=false; + //Set activate default eps bearer (esm_ms) //Set pdn_addr act_def_eps_bearer_context_req.pdn_addr.pdn_type = LIBLTE_MME_PDN_TYPE_IPV4; @@ -491,6 +502,10 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE std::string apn("internet"); act_def_eps_bearer_context_req.apn.apn = apn; //FIXME + act_def_eps_bearer_context_req.proc_transaction_id = 1; //FIXME + + //Make sure unused options are set to false + /* typedef struct{ LIBLTE_MME_EPS_QUALITY_OF_SERVICE_STRUCT eps_qos; //TODO @@ -513,8 +528,10 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE bool br_ext_present; }LIBLTE_MME_EPS_QUALITY_OF_SERVICE_STRUCT; */ - + uint8_t sec_hdr_type =3; + ue_ctx->security_ctxt.dl_nas_count++; liblte_mme_pack_activate_default_eps_bearer_context_request_msg(&act_def_eps_bearer_context_req, &attach_accept.esm_msg); + liblte_mme_pack_attach_accept_msg(&attach_accept, sec_hdr_type, ue_ctx->security_ctxt.dl_nas_count, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); //Integrity protect NAS message uint8_t mac[4]; srslte::security_128_eia1 (&ue_ctx->security_ctxt.k_nas_int[16], @@ -529,6 +546,11 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE memcpy(&nas_buffer->msg[1],mac,4); m_s1ap_log->info("Packed Attach Complete\n"); + //Add nas message to context setup request + erab_ctxt->nAS_PDU_present = true; + memcpy(erab_ctxt->nAS_PDU.buffer, nas_buffer->msg, nas_buffer->N_bytes); + erab_ctxt->nAS_PDU.n_octets = nas_buffer->N_bytes; + return true; } From 47576aced1a9bfea1bd3bbf1d5526606c09033e2 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 1 Dec 2017 12:37:34 +0000 Subject: [PATCH 106/172] Starting to add Init Context Setup Response Parsing. --- srsepc/hdr/mme/s1ap.h | 2 ++ srsepc/src/mme/s1ap.cc | 20 ++++++++++++++++---- srsepc/src/spgw/spgw.cc | 14 +++++++------- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index ebf4ae60d..828c1647a 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -82,7 +82,9 @@ public: bool handle_nas_authentication_response(srslte::byte_buffer_t *nas_buffer, srslte::byte_buffer_t *reply_buffer, ue_ctx_t *ue_ctx); bool handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx); bool send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp); + bool handle_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *msg); + bool handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *in_ctxt_resp); void print_enb_ctx_info(const enb_ctx_t &enb_ctx); private: diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 0544b5311..f8d75d35a 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -224,7 +224,7 @@ s1ap::handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb break; case LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME: m_s1ap_log->info("Received Succeseful Outcome PDU\n"); - return true;//TODO handle_successfuloutcome(&rx_pdu.choice.successfulOutcome); + return handle_successful_outcome(&rx_pdu.choice.successfulOutcome); break; case LIBLTE_S1AP_S1AP_PDU_CHOICE_UNSUCCESSFULOUTCOME: m_s1ap_log->info("Received Unsucceseful Outcome PDU\n"); @@ -261,6 +261,18 @@ s1ap::handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, stru return true; } +bool +s1ap::handle_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *msg) +{ + switch(msg->choice_type) { + case LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_INITIALCONTEXTSETUPRESPONSE: + m_s1ap_log->info("Received Initial Context Setup Response.\n"); + return handle_initial_context_setup_response(&msg->choice.InitialContextSetupResponse); + default: + m_s1ap_log->error("Unhandled successful outcome message: %s\n", liblte_s1ap_successfuloutcome_choice_text[msg->choice_type]); + } + return true; +} bool s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri) { @@ -655,13 +667,13 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: return true; } - /* + bool -s1ap::handle_initial_context_setup_response(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp) +s1ap::handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *in_ctxt_resp) { return true; } - */ + bool s1ap::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri) diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index 19c206f6e..b5f5773cb 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -256,7 +256,7 @@ spgw::run_thread() FD_SET(m_s1u, &set); FD_SET(sgi, &set); - m_spgw_log->info("Waiting for S1-U or SGi packets.\n"); + //m_spgw_log->info("Waiting for S1-U or SGi packets.\n"); int n = select(max_fd+1, &set, NULL, NULL, NULL); if (n == -1) { @@ -264,19 +264,19 @@ spgw::run_thread() } else if (n) { - m_spgw_log->info("Data is available now.\n"); + //m_spgw_log->info("Data is available now.\n"); if (FD_ISSET(m_s1u, &set)) { msg->N_bytes = recvfrom(m_s1u, msg->msg, SRSLTE_MAX_BUFFER_SIZE_BYTES, 0, &src_addr, &addrlen ); - m_spgw_log->console("Received PDU from S1-U. Bytes %d\n", msg->N_bytes); - m_spgw_log->debug("Received PDU from S1-U. Bytes %d\n", msg->N_bytes); + //m_spgw_log->console("Received PDU from S1-U. Bytes %d\n", msg->N_bytes); + //m_spgw_log->debug("Received PDU from S1-U. Bytes %d\n", msg->N_bytes); } if (FD_ISSET(m_sgi_if, &set)) { - m_spgw_log->console("Received PDU from SGi\n"); + //m_spgw_log->console("Received PDU from SGi\n"); msg->N_bytes = read(sgi, msg->msg, SRSLTE_MAX_BUFFER_SIZE_BYTES); - m_spgw_log->console("Received PDU from SGi. Bytes %d\n", msg->N_bytes); - m_spgw_log->debug("Received PDU from SGi. Bytes %d\n", msg->N_bytes); + //m_spgw_log->console("Received PDU from SGi. Bytes %d\n", msg->N_bytes); + //m_spgw_log->debug("Received PDU from SGi. Bytes %d\n", msg->N_bytes); } } else From 0a36f00d2ef4ecff5ff496567a4d370401bab45c Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 1 Dec 2017 14:58:01 +0000 Subject: [PATCH 107/172] Starting to decode initial context setup response. --- srsepc/hdr/mme/s1ap.h | 2 ++ srsepc/src/mme/s1ap.cc | 50 +++++++++++++++++++++++++++- srsepc/src/mme/s1ap_nas_transport.cc | 2 +- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 828c1647a..5df4dce71 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -85,6 +85,8 @@ public: bool handle_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *msg); bool handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *in_ctxt_resp); + bool handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx); + void print_enb_ctx_info(const enb_ctx_t &enb_ctx); private: diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index f8d75d35a..5d9cd1868 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -460,6 +460,11 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT handle_nas_security_mode_complete(nas_msg, reply_msg, ue_ctx); return true; //no need for reply. FIXME this should be better structured... break; + case LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE: + m_s1ap_log->info("UL NAS: Received Attach Complete\n"); + handle_nas_attach_complete(nas_msg, reply_msg, ue_ctx); + return true; //no need for reply. FIXME this should be better structured... + break; default: m_s1ap_log->info("Unhandled NAS message"); return false; //FIXME (nas_msg deallocate needs to be called) @@ -559,6 +564,14 @@ s1ap::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, srslte:: return true; } + +bool +s1ap::handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx) +{ + return true; +} + + bool s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp) { @@ -671,7 +684,42 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: bool s1ap::handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *in_ctxt_resp) { - return true; + /*typedef struct{ + bool ext; + LIBLTE_S1AP_MME_UE_S1AP_ID_STRUCT MME_UE_S1AP_ID; + LIBLTE_S1AP_ENB_UE_S1AP_ID_STRUCT eNB_UE_S1AP_ID; + LIBLTE_S1AP_E_RABSETUPLISTCTXTSURES_STRUCT E_RABSetupListCtxtSURes; + LIBLTE_S1AP_E_RABLIST_STRUCT E_RABFailedToSetupListCtxtSURes; + bool E_RABFailedToSetupListCtxtSURes_present; + LIBLTE_S1AP_CRITICALITYDIAGNOSTICS_STRUCT CriticalityDiagnostics; + bool CriticalityDiagnostics_present; + }LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT; + typedef struct{ + uint32_t len; + LIBLTE_S1AP_E_RABSETUPITEMCTXTSURES_STRUCT buffer[32]; //WARNING: Artificial limit to reduce memory footprint + }LIBLTE_S1AP_E_RABSETUPLISTCTXTSURES_STRUCT; + typedef struct{ + bool ext; + LIBLTE_S1AP_E_RAB_ID_STRUCT e_RAB_ID; + LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT transportLayerAddress; + LIBLTE_S1AP_GTP_TEID_STRUCT gTP_TEID; + LIBLTE_S1AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; + bool iE_Extensions_present; + }LIBLTE_S1AP_E_RABSETUPITEMCTXTSURES_STRUCT; + */ + erabs_it = m_active_erabs.find(in_ctxt_resp->MME_UE_S1AP_ID.MME_UE_S1AP_ID); + if (erabs_it == m_active_erabs.end()) + { + m_s1ap_log->error("Could not find UE's in UE active bearers map\n"); + return false; + } + else{ + for(int i; isecond.insert(std::pair<>()); + } + } + return true; } diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 835241397..a052b3356 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -220,7 +220,7 @@ s1ap_nas_transport::unpack_authentication_response(LIBLTE_S1AP_MESSAGE_UPLINKNAS liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &pd, &msg_type); if(msg_type!=LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE){ - m_s1ap_log->error("Unhandled NAS message within UL NAS Transport message\n"); + m_s1ap_log->error("Error unpacking NAS authentication response\n"); return false; } From c4c0a61d3cecddd991ed36caaf6bfae499772054 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 1 Dec 2017 17:41:45 +0000 Subject: [PATCH 108/172] Continuing to work on context setup response. --- srsepc/hdr/mme/s1ap.h | 10 +++++----- srsepc/hdr/mme/s1ap_common.h | 32 ++++++++++++++++++++++---------- srsepc/src/mme/s1ap.cc | 28 +++++++++++++++++++++------- 3 files changed, 48 insertions(+), 22 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 5df4dce71..c688523e8 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -101,11 +101,11 @@ private: hss *m_hss; int m_s1mme; - std::map m_active_enbs; - std::map m_sctp_to_enb_id; - std::map m_active_ues; - std::map > m_enb_id_to_ue_ids; - uint32_t m_next_mme_ue_s1ap_id; + std::map m_active_enbs; + std::map m_sctp_to_enb_id; + std::map m_active_ues; + std::map > m_enb_id_to_ue_ids; + uint32_t m_next_mme_ue_s1ap_id; s1ap_mngmt_proc m_s1ap_mngmt_proc; s1ap_nas_transport m_s1ap_nas_transport; diff --git a/srsepc/hdr/mme/s1ap_common.h b/srsepc/hdr/mme/s1ap_common.h index ad004190d..3c13e669e 100644 --- a/srsepc/hdr/mme/s1ap_common.h +++ b/srsepc/hdr/mme/s1ap_common.h @@ -22,11 +22,13 @@ #define S1AP_COMMON_H #include "srslte/common/security.h" +#include "srslte/asn1/gtpc_ies.h" namespace srsepc{ static const uint8_t MAX_TA=255; //Maximum TA supported static const uint8_t MAX_BPLMN=6; //Maximum broadcasted PLMNs per TAC +static const uint8_t MAX_ERABS_PER_UE = 16; typedef struct{ uint8_t mme_code; @@ -52,22 +54,32 @@ typedef struct{ struct sctp_sndrcvinfo sri; } enb_ctx_t; +typedef struct{ + uint8_t k_asme[32]; + uint8_t xres[8]; + uint32_t dl_nas_count; + uint32_t ul_nas_count; + srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo; + srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo; + uint8_t k_nas_enc[32]; + uint8_t k_nas_int[32]; +} eps_security_ctx_t; + +typedef struct{ + bool active; + uint8_t erab_id; + srslte::gtpc_f_teid_ie enb_fteid; + //gtpc_f_teid_ie sgw_fteid; //? +} erab_ctx_t; + typedef struct{ uint64_t imsi; uint32_t enb_ue_s1ap_id; uint32_t mme_ue_s1ap_id; uint16_t enb_id; struct sctp_sndrcvinfo enb_sri; - struct eps_security_ctxt{ - uint8_t k_asme[32]; - uint8_t xres[8]; - uint32_t dl_nas_count; - uint32_t ul_nas_count; - srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo; - srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo; - uint8_t k_nas_enc[32]; - uint8_t k_nas_int[32]; - } security_ctxt; + eps_security_ctx_t security_ctxt; + erab_ctx_t erabs[MAX_ERABS_PER_UE]; } ue_ctx_t; }//namespace #endif diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 5d9cd1868..c64977a2a 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -707,18 +707,32 @@ s1ap::handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSE bool iE_Extensions_present; }LIBLTE_S1AP_E_RABSETUPITEMCTXTSURES_STRUCT; */ - erabs_it = m_active_erabs.find(in_ctxt_resp->MME_UE_S1AP_ID.MME_UE_S1AP_ID); - if (erabs_it == m_active_erabs.end()) + uint32_t mme_ue_s1ap_id = in_ctxt_resp->MME_UE_S1AP_ID.MME_UE_S1AP_ID; + std::map ue_ctx_it = m_acive_ues.find(mme_ue_s1ap_id); + if (ue_ctx_it == m_active_ues.end()) { - m_s1ap_log->error("Could not find UE's in UE active bearers map\n"); + m_s1ap_log->error("Could not find UE's context in active UE's map\n"); return false; } - else{ - for(int i; iE_RABSetupListCtxtSURes.len;i++) + { + uint8_t erab_id = in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].e_RAB_ID.E_RAB_ID; + if (erab_ctx->active == false) { - erabs_it->second.insert(std::pair<>()); + m_s1ap_log->error("E-RAB requested was not active %d\n",); + return false; + } + erab_ctx_t *erab_ctx = &ue_ctx_it->second->erab_ctx[i]; + for(uint32_t i; iE_RABSetupListCtxtSURes.len;i++) + { + uint8_t erab_id = in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].e_RAB_ID.E_RAB_ID; + std::set ue_erab_it = erabs_it->second.find(erab_id); + if(ue_erab_it == erabs_it->second.end() ) + { + m_s1ap_log->error("Could not find UE's in UE active bearers map\n"); + return false; + } } - } return true; } From b2826402b93fdbc3a3c46a4be5f543f903f09178 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 4 Dec 2017 10:54:47 +0000 Subject: [PATCH 109/172] Continuing to parse intial context setup --- srsepc/hdr/mme/s1ap_common.h | 2 +- srsepc/src/mme/s1ap.cc | 25 +++++++++---------------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/srsepc/hdr/mme/s1ap_common.h b/srsepc/hdr/mme/s1ap_common.h index 3c13e669e..803a66ecf 100644 --- a/srsepc/hdr/mme/s1ap_common.h +++ b/srsepc/hdr/mme/s1ap_common.h @@ -79,7 +79,7 @@ typedef struct{ uint16_t enb_id; struct sctp_sndrcvinfo enb_sri; eps_security_ctx_t security_ctxt; - erab_ctx_t erabs[MAX_ERABS_PER_UE]; + erab_ctx_t erabs_ctx[MAX_ERABS_PER_UE]; } ue_ctx_t; }//namespace #endif diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index c64977a2a..7ec26af32 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -663,15 +663,14 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: m_s1ap_log->error("Could not pack Initial Context Setup Request Message\n"); return false; } - //Send Reply to eNB - + //Send Reply to eNB ssize_t n_sent = sctp_send(m_s1mme,reply_buffer->msg, reply_buffer->N_bytes, &ue_ctx->enb_sri, 0); if(n_sent == -1) { m_s1ap_log->error("Failed to send Initial Context Setup Request\n"); return false; } - + m_s1ap_log->info("Sent Intial Context Setup Request\n"); m_s1ap_log->console("Sent Intial Context Setup Request\n"); @@ -708,7 +707,7 @@ s1ap::handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSE }LIBLTE_S1AP_E_RABSETUPITEMCTXTSURES_STRUCT; */ uint32_t mme_ue_s1ap_id = in_ctxt_resp->MME_UE_S1AP_ID.MME_UE_S1AP_ID; - std::map ue_ctx_it = m_acive_ues.find(mme_ue_s1ap_id); + std::map::iterator ue_ctx_it = m_active_ues.find(mme_ue_s1ap_id); if (ue_ctx_it == m_active_ues.end()) { m_s1ap_log->error("Could not find UE's context in active UE's map\n"); @@ -717,22 +716,16 @@ s1ap::handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSE for(uint32_t i; iE_RABSetupListCtxtSURes.len;i++) { uint8_t erab_id = in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].e_RAB_ID.E_RAB_ID; + erab_ctx_t *erab_ctx = &ue_ctx_it->second->erabs_ctx[erab_id]; if (erab_ctx->active == false) { - m_s1ap_log->error("E-RAB requested was not active %d\n",); + m_s1ap_log->error("E-RAB requested was not active %d\n",erab_id); return false; } - erab_ctx_t *erab_ctx = &ue_ctx_it->second->erab_ctx[i]; - for(uint32_t i; iE_RABSetupListCtxtSURes.len;i++) - { - uint8_t erab_id = in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].e_RAB_ID.E_RAB_ID; - std::set ue_erab_it = erabs_it->second.find(erab_id); - if(ue_erab_it == erabs_it->second.end() ) - { - m_s1ap_log->error("Could not find UE's in UE active bearers map\n"); - return false; - } - } + //Set the GTP information + memcpy(&erab_ctx->enb_fteid.ipv4, in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].transportLayerAddress.buffer,4); + memcpy(&erab_ctx->enb_fteid.teid, in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].gTP_TEID.buffer, 4); + } return true; } From 8becf4ab237a839026c2c2d32ff1456216ca0cfc Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 4 Dec 2017 16:00:53 +0000 Subject: [PATCH 110/172] Unpacking Activate EPS Bearer Context Accept. --- srsepc/hdr/mme/s1ap_common.h | 10 +++- srsepc/src/mme/s1ap.cc | 100 +++++++++++++++++++++++++---------- 2 files changed, 81 insertions(+), 29 deletions(-) diff --git a/srsepc/hdr/mme/s1ap_common.h b/srsepc/hdr/mme/s1ap_common.h index 803a66ecf..cdd0f0bab 100644 --- a/srsepc/hdr/mme/s1ap_common.h +++ b/srsepc/hdr/mme/s1ap_common.h @@ -30,6 +30,14 @@ static const uint8_t MAX_TA=255; //Maximum TA supported static const uint8_t MAX_BPLMN=6; //Maximum broadcasted PLMNs per TAC static const uint8_t MAX_ERABS_PER_UE = 16; +enum erab_state +{ + ERAB_DEACTIVATED, + ERAB_CTX_REQUESTED, + ERAB_CTX_SETUP, + ERAB_ACTIVE +}; + typedef struct{ uint8_t mme_code; uint16_t mme_group; @@ -66,7 +74,7 @@ typedef struct{ } eps_security_ctx_t; typedef struct{ - bool active; + enum erab_state state; uint8_t erab_id; srslte::gtpc_f_teid_ie enb_fteid; //gtpc_f_teid_ie sgw_fteid; //? diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 7ec26af32..4ec10c59d 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -391,7 +391,12 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini //Save UE context ue_ctx.imsi = imsi; ue_ctx.mme_ue_s1ap_id = m_next_mme_ue_s1ap_id++; - + for(uint i = 0 ; i< MAX_ERABS_PER_UE; i++) + { + ue_ctx.erabs_ctx[i].state = ERAB_DEACTIVATED; + ue_ctx.erabs_ctx[i].erab_id = i; + } + ue_ctx_t *ue_ptr = new ue_ctx_t; memcpy(ue_ptr,&ue_ctx,sizeof(ue_ctx)); m_active_ues.insert(std::pair(ue_ptr->mme_ue_s1ap_id,ue_ptr)); @@ -568,7 +573,48 @@ s1ap::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, srslte:: bool s1ap::handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx) { - return true; + /* + typedef struct{ + LIBLTE_BYTE_MSG_STRUCT esm_msg; + }LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT; + */ + /* + typedef struct{ + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + bool protocol_cnfg_opts_present; + }LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT; + */ + LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT attach_comp; + uint8_t pd, msg_type; + srslte::byte_buffer_t *esm_msg = m_pool->allocate(); + LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT act_bearer; + + //Get NAS authentication response + LIBLTE_ERROR_ENUM err = liblte_mme_unpack_attach_complete_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &attach_comp); + if(err != LIBLTE_SUCCESS){ + m_s1ap_log->error("Error unpacking NAS authentication response. Error: %s\n", liblte_error_text[err]); + return false; + } + + memcpy(esm_msg->msg, attach_comp.esm_msg.buffer, attach_comp.esm_msg.N_bytes); + esm_msg->N_bytes = attach_comp.esm_msg.N_bytes; + /*liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) esm_msg, &pd, &msg_type); + if(msg_type!= LIBLTE_MME_MSG_TYPE_ACTIVATE_DEFAULT_EPS_BEARER_ACCEPT){ + m_s1ap_log->error("Error unpacking activate default eps bearer context accept\n"); + return false; + }*/ + + err = liblte_mme_pack_activate_default_eps_bearer_context_accept_msg(&act_bearer, (LIBLTE_BYTE_MSG_STRUCT *) esm_msg); + if(err != LIBLTE_SUCCESS){ + m_s1ap_log->error("Error unpacking Activate EPS Bearer Context Accept Msg. Error: %s\n", liblte_error_text[err]); + return false; + } + + m_s1ap_log->console("Unpacked Attached Complete Message\n"); + m_s1ap_log->console("Unpacked Activavate Default EPS Bearer message\n"); + return true; } @@ -657,7 +703,6 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: m_s1ap_nas_transport.pack_attach_accept(ue_ctx, erab_ctxt, &cs_resp->paa, nas_buffer); LIBLTE_ERROR_ENUM err = liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)reply_buffer); - //reply_buffer->N_bytes = pdu->NAS_PDU.n_octets; if(err != LIBLTE_SUCCESS) { m_s1ap_log->error("Could not pack Initial Context Setup Request Message\n"); @@ -671,6 +716,9 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: return false; } + //Change E-RAB state to Context Setup Requested + ue_ctx->erabs_ctx[erab_ctxt->e_RAB_ID.E_RAB_ID].state = ERAB_CTX_REQUESTED; + m_s1ap_log->info("Sent Intial Context Setup Request\n"); m_s1ap_log->console("Sent Intial Context Setup Request\n"); @@ -683,29 +731,7 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: bool s1ap::handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *in_ctxt_resp) { - /*typedef struct{ - bool ext; - LIBLTE_S1AP_MME_UE_S1AP_ID_STRUCT MME_UE_S1AP_ID; - LIBLTE_S1AP_ENB_UE_S1AP_ID_STRUCT eNB_UE_S1AP_ID; - LIBLTE_S1AP_E_RABSETUPLISTCTXTSURES_STRUCT E_RABSetupListCtxtSURes; - LIBLTE_S1AP_E_RABLIST_STRUCT E_RABFailedToSetupListCtxtSURes; - bool E_RABFailedToSetupListCtxtSURes_present; - LIBLTE_S1AP_CRITICALITYDIAGNOSTICS_STRUCT CriticalityDiagnostics; - bool CriticalityDiagnostics_present; - }LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT; - typedef struct{ - uint32_t len; - LIBLTE_S1AP_E_RABSETUPITEMCTXTSURES_STRUCT buffer[32]; //WARNING: Artificial limit to reduce memory footprint - }LIBLTE_S1AP_E_RABSETUPLISTCTXTSURES_STRUCT; - typedef struct{ - bool ext; - LIBLTE_S1AP_E_RAB_ID_STRUCT e_RAB_ID; - LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT transportLayerAddress; - LIBLTE_S1AP_GTP_TEID_STRUCT gTP_TEID; - LIBLTE_S1AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; - bool iE_Extensions_present; - }LIBLTE_S1AP_E_RABSETUPITEMCTXTSURES_STRUCT; - */ + uint32_t mme_ue_s1ap_id = in_ctxt_resp->MME_UE_S1AP_ID.MME_UE_S1AP_ID; std::map::iterator ue_ctx_it = m_active_ues.find(mme_ue_s1ap_id); if (ue_ctx_it == m_active_ues.end()) @@ -717,14 +743,32 @@ s1ap::handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSE { uint8_t erab_id = in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].e_RAB_ID.E_RAB_ID; erab_ctx_t *erab_ctx = &ue_ctx_it->second->erabs_ctx[erab_id]; - if (erab_ctx->active == false) + if (erab_ctx->state != ERAB_CTX_REQUESTED) { m_s1ap_log->error("E-RAB requested was not active %d\n",erab_id); return false; } + //Mark E-RAB with context setup + erab_ctx->state = ERAB_CTX_SETUP; + //Set the GTP information - memcpy(&erab_ctx->enb_fteid.ipv4, in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].transportLayerAddress.buffer,4); + uint8_t *bit_ptr = in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].transportLayerAddress.buffer; + erab_ctx->enb_fteid.ipv4 = htonl(liblte_bits_2_value(&bit_ptr,32)); memcpy(&erab_ctx->enb_fteid.teid, in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].gTP_TEID.buffer, 4); + erab_ctx->enb_fteid.teid = ntohl(erab_ctx->enb_fteid.teid); + + char enb_addr_str[INET_ADDRSTRLEN+1]; + const char *err = inet_ntop(AF_INET, &erab_ctx->enb_fteid.ipv4,enb_addr_str,sizeof(enb_addr_str)); + if(err == NULL) + { + m_s1ap_log->error("Error converting IP to string\n"); + } + + m_s1ap_log->info("E-RAB Context Setup. E-RAB id %d\n",erab_ctx->erab_id); + m_s1ap_log->info("E-RAB Context -- eNB TEID 0x%x, eNB Address %s\n", erab_ctx->enb_fteid.teid, enb_addr_str); + m_s1ap_log->console("E-RAB Context Setup. E-RAB id %d\n",erab_ctx->erab_id); + m_s1ap_log->console("E-RAB Context -- eNB TEID 0x%x; eNB GTP-U Address %s\n", erab_ctx->enb_fteid.teid, enb_addr_str); + } return true; } From 9f994dba04013a2446f3f110ab3550e1827eef87 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 5 Dec 2017 17:21:46 +0000 Subject: [PATCH 111/172] Starting to generate modify bearer request. Fixed bug in unpacking activate default bearer accept. --- lib/include/srslte/asn1/gtpc_msg.h | 52 +++++++++++-- srsepc/hdr/mme/mme_gtpc.h | 3 +- srsepc/hdr/mme/s1ap.h | 2 +- srsepc/hdr/mme/s1ap_common.h | 4 +- srsepc/src/mme/mme_gtpc.cc | 36 ++++++++- srsepc/src/mme/s1ap.cc | 111 ++++++++++++++------------- srsepc/src/mme/s1ap_nas_transport.cc | 1 + 7 files changed, 145 insertions(+), 64 deletions(-) diff --git a/lib/include/srslte/asn1/gtpc_msg.h b/lib/include/srslte/asn1/gtpc_msg.h index 86cf96046..686f9d9ce 100644 --- a/lib/include/srslte/asn1/gtpc_msg.h +++ b/lib/include/srslte/asn1/gtpc_msg.h @@ -234,12 +234,12 @@ struct gtpc_create_session_request //bool ext; // O }; - /**************************************************************************** - * - * GTP-C v2 Create Session Response - * Ref: 3GPP TS 29.274 v10.14.0 Table 7.2.2-1 - * - ***************************************************************************/ +/**************************************************************************** + * + * GTP-C v2 Create Session Response + * Ref: 3GPP TS 29.274 v10.14.0 Table 7.2.2-1 + * + ***************************************************************************/ struct gtpc_create_session_response { struct gtpc_cause_ie cause; //M @@ -294,5 +294,45 @@ struct gtpc_create_session_response //acpo //CO }; +/**************************************************************************** + * + * GTP-C v2 Modify Bearer Request + * Ref: 3GPP TS 29.274 v10.14.0 Table 7.2.7-1, 7.2.7-2 and 7.2.7-3 + * + ***************************************************************************/ + +struct gtpc_modify_bearer_request +{ + //ME Identity (MEI)//C + //User Location Information (ULI)//C + //Serving Network //CO + //RAT Type //C/CO + //Indication Flags + //Sender F-TEID for Control Plane + //APN-AMBR + //Delay Downlink Packet Notification Request + struct gtpc_bearer_context_modified_ie + { + uint8_t ebi; + gtpc_cause_ie cause; + bool s1_u_enb_f_teid_present; + struct gtpc_f_teid_ie s1_u_enb_f_teid; + bool s5_s8_u_sgw_f_teid_present; + struct gtpc_f_teid_ie s5_s8_u_sgw_f_teid; + bool s12_rnc_f_teid_present; + struct gtpc_f_teid_ie s12_rnc_f_teid; + bool s4_u_sgsn_f_teid_present; + struct gtpc_f_teid_ie s4_u_sgsn_f_teid; + } eps_bearer_context_to_modify; + //Bearer Contexts to be removed + //Recovery + //UE Time Zone + //MME-FQ-CSID + //SGW-FQ-CSID + //User CSG Information (UCI) + //MME/S4-SGSN LDN + //SGW LDN +}; + }; //namespace #endif //GTPC_V2_MSG_H diff --git a/srsepc/hdr/mme/mme_gtpc.h b/srsepc/hdr/mme/mme_gtpc.h index 17cc23189..f41863698 100644 --- a/srsepc/hdr/mme/mme_gtpc.h +++ b/srsepc/hdr/mme/mme_gtpc.h @@ -31,7 +31,7 @@ #include "srslte/common/buffer_pool.h" #include #include "srslte/asn1/gtpc.h" - +#include "mme/s1ap_common.h" namespace srsepc { @@ -50,6 +50,7 @@ public: uint32_t get_new_ctrl_teid(); void send_create_session_request(uint64_t imsi, uint32_t mme_s1ap_id); void handle_create_session_response(srslte::gtpc_pdu *cs_resp_pdu); + void send_modify_bearer_request(erab_ctx_t *bearer_ctx); private: diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index c688523e8..0d0f0a598 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -81,7 +81,7 @@ public: bool handle_nas_authentication_response(srslte::byte_buffer_t *nas_buffer, srslte::byte_buffer_t *reply_buffer, ue_ctx_t *ue_ctx); bool handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx); - bool send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp); + bool send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp, struct srslte::gtpc_f_teid_ie sgw_ctrl_fteid); bool handle_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *msg); bool handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *in_ctxt_resp); diff --git a/srsepc/hdr/mme/s1ap_common.h b/srsepc/hdr/mme/s1ap_common.h index cdd0f0bab..759f2d316 100644 --- a/srsepc/hdr/mme/s1ap_common.h +++ b/srsepc/hdr/mme/s1ap_common.h @@ -23,6 +23,8 @@ #include "srslte/common/security.h" #include "srslte/asn1/gtpc_ies.h" +#include "srslte/asn1/liblte_s1ap.h" +#include namespace srsepc{ @@ -77,7 +79,7 @@ typedef struct{ enum erab_state state; uint8_t erab_id; srslte::gtpc_f_teid_ie enb_fteid; - //gtpc_f_teid_ie sgw_fteid; //? + srslte::gtpc_f_teid_ie sgw_ctrl_fteid; } erab_ctx_t; typedef struct{ diff --git a/srsepc/src/mme/mme_gtpc.cc b/srsepc/src/mme/mme_gtpc.cc index 20ed20f50..7c314a9a7 100644 --- a/srsepc/src/mme/mme_gtpc.cc +++ b/srsepc/src/mme/mme_gtpc.cc @@ -143,8 +143,8 @@ mme_gtpc::handle_create_session_response(srslte::gtpc_pdu *cs_resp_pdu) //TODO Handle error return; } - - //Get MME_UE_S1AP_ID from the Ctrl TEID + + //Get MME_UE_S1AP_ID from the control TEID std::map::iterator id_it = m_teid_to_mme_s1ap_id.find(cs_resp_pdu->header.teid); if(id_it == m_teid_to_mme_s1ap_id.end()) { @@ -153,7 +153,37 @@ mme_gtpc::handle_create_session_response(srslte::gtpc_pdu *cs_resp_pdu) return; } uint32_t mme_s1ap_id = id_it->second; - m_s1ap->send_initial_context_setup_request(mme_s1ap_id, cs_resp); + + //Get S-GW Control F-TEID + srslte::gtpc_f_teid_ie sgw_ctrl_fteid; + sgw_ctrl_fteid.teid = cs_resp_pdu->header.teid; + sgw_ctrl_fteid.ipv4 = 0; //FIXME This is not used for now. In the future it will be obtained from the socket addr_info + + m_s1ap->send_initial_context_setup_request(mme_s1ap_id, cs_resp, sgw_ctrl_fteid); } + +void +mme_gtpc::send_modify_bearer_request(erab_ctx_t *erab_ctx) +{ + m_mme_gtpc_log->info("Sending GTP-C Modify bearer request\n"); + srslte::gtpc_pdu pdu; + srslte::gtpc_f_teid_ie *enb_fteid = &erab_ctx->enb_fteid; + srslte::gtpc_f_teid_ie *sgw_ctrl_fteid = &erab_ctx->sgw_ctrl_fteid; + + srslte::gtpc_header *header = &pdu.header; + header->teid_present = true; + header->teid = sgw_ctrl_fteid->teid; + header->type = srslte::GTPC_MSG_TYPE_MODIFY_BEARER_REQUEST; + + srslte::gtpc_modify_bearer_request mb_req; + mb_req.eps_bearer_context_to_modify.ebi = erab_ctx->erab_id; + mb_req.eps_bearer_context_to_modify.s1_u_enb_f_teid.ipv4 = enb_fteid->ipv4; + mb_req.eps_bearer_context_to_modify.s1_u_enb_f_teid.teid = enb_fteid->teid; + + m_mme_gtpc_log->info("GTP-C Modify bearer request -- S-GW Control TEID %d\n", sgw_ctrl_fteid->teid ); + m_mme_gtpc_log->info("GTP-C Modify bearer request -- S1-U TEID 0x%x\n", enb_fteid->teid ); + + +} } //namespace srsepc diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 4ec10c59d..a58ac6a40 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -570,56 +570,9 @@ s1ap::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, srslte:: } -bool -s1ap::handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx) -{ - /* - typedef struct{ - LIBLTE_BYTE_MSG_STRUCT esm_msg; - }LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT; - */ - /* - typedef struct{ - LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; - uint8 eps_bearer_id; - uint8 proc_transaction_id; - bool protocol_cnfg_opts_present; - }LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT; - */ - LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT attach_comp; - uint8_t pd, msg_type; - srslte::byte_buffer_t *esm_msg = m_pool->allocate(); - LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT act_bearer; - - //Get NAS authentication response - LIBLTE_ERROR_ENUM err = liblte_mme_unpack_attach_complete_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &attach_comp); - if(err != LIBLTE_SUCCESS){ - m_s1ap_log->error("Error unpacking NAS authentication response. Error: %s\n", liblte_error_text[err]); - return false; - } - - memcpy(esm_msg->msg, attach_comp.esm_msg.buffer, attach_comp.esm_msg.N_bytes); - esm_msg->N_bytes = attach_comp.esm_msg.N_bytes; - /*liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) esm_msg, &pd, &msg_type); - if(msg_type!= LIBLTE_MME_MSG_TYPE_ACTIVATE_DEFAULT_EPS_BEARER_ACCEPT){ - m_s1ap_log->error("Error unpacking activate default eps bearer context accept\n"); - return false; - }*/ - - err = liblte_mme_pack_activate_default_eps_bearer_context_accept_msg(&act_bearer, (LIBLTE_BYTE_MSG_STRUCT *) esm_msg); - if(err != LIBLTE_SUCCESS){ - m_s1ap_log->error("Error unpacking Activate EPS Bearer Context Accept Msg. Error: %s\n", liblte_error_text[err]); - return false; - } - - m_s1ap_log->console("Unpacked Attached Complete Message\n"); - m_s1ap_log->console("Unpacked Activavate Default EPS Bearer message\n"); - return true; -} - bool -s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp) +s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp, struct srslte::gtpc_f_teid_ie sgw_ctrl_fteid) { ue_ctx_t *ue_ctx; @@ -701,7 +654,7 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: } srslte::byte_buffer_t *nas_buffer = m_pool->allocate(); m_s1ap_nas_transport.pack_attach_accept(ue_ctx, erab_ctxt, &cs_resp->paa, nas_buffer); - + LIBLTE_ERROR_ENUM err = liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)reply_buffer); if(err != LIBLTE_SUCCESS) { @@ -716,11 +669,13 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: return false; } - //Change E-RAB state to Context Setup Requested + //Change E-RAB state to Context Setup Requested and save S-GW control F-TEID ue_ctx->erabs_ctx[erab_ctxt->e_RAB_ID.E_RAB_ID].state = ERAB_CTX_REQUESTED; + ue_ctx->erabs_ctx[erab_ctxt->e_RAB_ID.E_RAB_ID].sgw_ctrl_fteid.teid = sgw_ctrl_fteid.teid; + ue_ctx->erabs_ctx[erab_ctxt->e_RAB_ID.E_RAB_ID].sgw_ctrl_fteid.ipv4 = sgw_ctrl_fteid.ipv4; - m_s1ap_log->info("Sent Intial Context Setup Request\n"); - m_s1ap_log->console("Sent Intial Context Setup Request\n"); + m_s1ap_log->info("Sent Intial Context Setup Request. E-RAB id %d \n",erab_ctxt->e_RAB_ID.E_RAB_ID); + m_s1ap_log->console("Sent Intial Context Setup Request, E-RAB id %d\n",erab_ctxt->e_RAB_ID.E_RAB_ID); m_pool->deallocate(reply_buffer); m_pool->deallocate(nas_buffer); @@ -773,6 +728,58 @@ s1ap::handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSE return true; } +bool +s1ap::handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx) +{ + /* + typedef struct{ + LIBLTE_BYTE_MSG_STRUCT esm_msg; + }LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT; + */ + /* + typedef struct{ + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + bool protocol_cnfg_opts_present; + }LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT; + */ + LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT attach_comp; + uint8_t pd, msg_type; + srslte::byte_buffer_t *esm_msg = m_pool->allocate(); + LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT act_bearer; + + m_s1ap_log->info_hex(nas_msg->msg, nas_msg->N_bytes, "NAS Attach complte"); + + //Get NAS authentication response + LIBLTE_ERROR_ENUM err = liblte_mme_unpack_attach_complete_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &attach_comp); + if(err != LIBLTE_SUCCESS){ + m_s1ap_log->error("Error unpacking NAS authentication response. Error: %s\n", liblte_error_text[err]); + return false; + } + + // memcpy(esm_msg->msg, attach_comp.esm_msg.buffer, attach_comp.esm_msg.N_bytes); + //esm_msg->N_bytes = attach_comp.esm_msg.N_bytes; + + err = liblte_mme_unpack_activate_default_eps_bearer_context_accept_msg( (LIBLTE_BYTE_MSG_STRUCT *) &attach_comp.esm_msg, &act_bearer); + if(err != LIBLTE_SUCCESS){ + m_s1ap_log->error("Error unpacking Activate EPS Bearer Context Accept Msg. Error: %s\n", liblte_error_text[err]); + return false; + } + + m_s1ap_log->console("Unpacked Attached Complete Message\n"); + m_s1ap_log->console("Unpacked Activavate Default EPS Bearer message. EPS Bearer id %d\n",act_bearer.eps_bearer_id); + //ue_ctx->erabs_ctx[act_bearer->eps_bearer_id].enb_fteid; + if(act_bearer.eps_bearer_id < 5 || act_bearer.eps_bearer_id > 16) + { + m_s1ap_log->error("EPS Bearer ID out of range\n"); + return false; + } + m_mme_gtpc->send_modify_bearer_request(&ue_ctx->erabs_ctx[act_bearer.eps_bearer_id]); + return true; +} + + bool s1ap::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri) diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index a052b3356..490fc46c4 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -490,6 +490,7 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE memcpy(act_def_eps_bearer_context_req.pdn_addr.addr, &paa->ipv4, 4); //Set eps bearer id act_def_eps_bearer_context_req.eps_bearer_id = erab_ctxt->e_RAB_ID.E_RAB_ID; + printf("%d\n",act_def_eps_bearer_context_req.eps_bearer_id); act_def_eps_bearer_context_req.transaction_id_present = false; //set eps_qos act_def_eps_bearer_context_req.eps_qos.qci = erab_ctxt->e_RABlevelQoSParameters.qCI.QCI; From 489865fa22131e4d7e21b5f7746938f95f4ee45a Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 5 Dec 2017 19:17:46 +0000 Subject: [PATCH 112/172] Starting to parse Modify Bearer Request at the S-GW. --- srsepc/hdr/spgw/spgw.h | 13 ++++++++----- srsepc/src/mme/mme_gtpc.cc | 14 ++++++++------ srsepc/src/spgw/spgw.cc | 35 +++++++++++++++++++++++++++-------- 3 files changed, 43 insertions(+), 19 deletions(-) diff --git a/srsepc/hdr/spgw/spgw.h b/srsepc/hdr/spgw/spgw.h index 12ec01d51..a9c1b9ba3 100644 --- a/srsepc/hdr/spgw/spgw.h +++ b/srsepc/hdr/spgw/spgw.h @@ -56,11 +56,11 @@ typedef struct { typedef struct { uint64_t imsi; in_addr_t ue_ipv4; - struct srslte::gtpc_f_teid_ie uplink_ctrl; - struct srslte::gtpc_f_teid_ie uplink_user; - struct srslte::gtpc_f_teid_ie downlink_ctrl; - struct srslte::gtpc_f_teid_ie downlink_user; -} spgw_ue_ctxr; + struct srslte::gtpc_f_teid_ie up_ctrl_fteid; + struct srslte::gtpc_f_teid_ie up_user_fteid; + struct srslte::gtpc_f_teid_ie dw_ctrl_fteid; + struct srslte::gtpc_f_teid_ie dw_user_fteid; +} spgw_ue_ctx; class spgw: public thread @@ -101,6 +101,9 @@ private: uint64_t m_next_ctrl_teid; uint64_t m_next_user_teid; + std::map m_teid_to_ue_ctx; //Map control TEID to ue_ctx. Usefull to get reply ctrl TEID + std::map m_ip_to_teid; //Map IP to User-plane TEID for downlink traffic + /*Logs*/ srslte::log_filter *m_spgw_log; diff --git a/srsepc/src/mme/mme_gtpc.cc b/srsepc/src/mme/mme_gtpc.cc index 7c314a9a7..75b811835 100644 --- a/srsepc/src/mme/mme_gtpc.cc +++ b/srsepc/src/mme/mme_gtpc.cc @@ -167,7 +167,7 @@ void mme_gtpc::send_modify_bearer_request(erab_ctx_t *erab_ctx) { m_mme_gtpc_log->info("Sending GTP-C Modify bearer request\n"); - srslte::gtpc_pdu pdu; + srslte::gtpc_pdu mb_req_pdu; srslte::gtpc_f_teid_ie *enb_fteid = &erab_ctx->enb_fteid; srslte::gtpc_f_teid_ie *sgw_ctrl_fteid = &erab_ctx->sgw_ctrl_fteid; @@ -176,14 +176,16 @@ mme_gtpc::send_modify_bearer_request(erab_ctx_t *erab_ctx) header->teid = sgw_ctrl_fteid->teid; header->type = srslte::GTPC_MSG_TYPE_MODIFY_BEARER_REQUEST; - srslte::gtpc_modify_bearer_request mb_req; - mb_req.eps_bearer_context_to_modify.ebi = erab_ctx->erab_id; - mb_req.eps_bearer_context_to_modify.s1_u_enb_f_teid.ipv4 = enb_fteid->ipv4; - mb_req.eps_bearer_context_to_modify.s1_u_enb_f_teid.teid = enb_fteid->teid; + srslte::gtpc_modify_bearer_request *mb_req = &mb_req_pdu.modify_bearer_request; + mb_req->eps_bearer_context_to_modify.ebi = erab_ctx->erab_id; + mb_req->eps_bearer_context_to_modify.s1_u_enb_f_teid.ipv4 = enb_fteid->ipv4; + mb_req->eps_bearer_context_to_modify.s1_u_enb_f_teid.teid = enb_fteid->teid; m_mme_gtpc_log->info("GTP-C Modify bearer request -- S-GW Control TEID %d\n", sgw_ctrl_fteid->teid ); m_mme_gtpc_log->info("GTP-C Modify bearer request -- S1-U TEID 0x%x\n", enb_fteid->teid ); - + // + srslte::gtpc_pdu mb_resp_pdu; + m_spgw->handle_modify_bearer_request(&mb_req_pdu,&mb_resp_pdu); } } //namespace srsepc diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index b5f5773cb..2f47de745 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -315,13 +315,7 @@ spgw::handle_create_session_request(struct srslte::gtpc_create_session_request * m_spgw_log->info("Received Create Session Request\n"); - //Setup GTP-C header - header->piggyback = false; - header->teid_present = true; - header->teid = cs_req->sender_f_teid.teid; //Send create session requesponse to the CS Request TEID - header->type = srslte::GTPC_MSG_TYPE_CREATE_SESSION_RESPONSE; - - //Setup uplink control TEID + //Setup uplink control TEID uint64_t spgw_uplink_ctrl_teid = get_new_ctrl_teid(); //Setup uplink user TEID uint64_t spgw_uplink_user_teid = get_new_user_teid(); @@ -329,9 +323,19 @@ spgw::handle_create_session_request(struct srslte::gtpc_create_session_request * in_addr_t ue_ip = get_new_ue_ipv4(); //Save the UE IP to User TEID map //TODO!!! + struct sgw_ue_ctx *ue_ctx = new sgw_ue_ctx; + sgw_ue_ctx->imsi = cs_req->imsi; + sgw_ue_ctx->ul_user_fteid.teid = spgw_uplink_user_teid; + sgw_ue_ctx->ul_ctrl_fteid = spgw_uplink_ctrl_teid; + sgw_ue_ctx->ue_ipv4 = ue_ip; //Create session response message - //Initialize to zero\\ + //Setup GTP-C header + header->piggyback = false; + header->teid_present = true; + header->teid = cs_req->sender_f_teid.teid; //Send create session requesponse to the CS Request TEID + header->type = srslte::GTPC_MSG_TYPE_CREATE_SESSION_RESPONSE; + //Initialize to zero bzero(cs_resp,sizeof(struct srslte::gtpc_create_session_response)); //Setup Cause cs_resp->cause.cause_value = srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED; @@ -354,6 +358,21 @@ spgw::handle_create_session_request(struct srslte::gtpc_create_session_request * return; } +void +spgw::handle_modify_bearer_request(struct srslte::gtpc_pdu *mb_req_pdu, struct srslte::gtpc_pdu *mb_resp_pdu) +{ + m_spgw_log->info("Received Modified Bearer Request\n"); + //Get control tunnel info from + //Setting up Modify bearer request PDU + //Header + srslte::gtpc_header *header = &mb_req_pdu->header; + header->piggyback = false; + header->teid_present = true; + header->teid = ; // + header->type = srslte::GTPC_MSG_TYPE_MODIFY_BEARER_RESPONSE; + //PDU + srslte::gtpc_modify_bearer_response *mb_resp = mb_req_pdu.choice.modify_bearer_response; +} } //namespace srsepc From d9725491248555d524c908fb40edc643a09d8648 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 6 Dec 2017 12:50:25 +0000 Subject: [PATCH 113/172] Starting to create structure for modify bearer response --- lib/include/srslte/asn1/gtpc.h | 2 ++ srsepc/hdr/spgw/spgw.h | 9 +++++---- srsepc/src/mme/mme_gtpc.cc | 2 +- srsepc/src/spgw/spgw.cc | 31 +++++++++++++++++++++++-------- 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/lib/include/srslte/asn1/gtpc.h b/lib/include/srslte/asn1/gtpc.h index e670333bf..e216bcf12 100644 --- a/lib/include/srslte/asn1/gtpc.h +++ b/lib/include/srslte/asn1/gtpc.h @@ -74,6 +74,8 @@ typedef union gtpc_msg_choice { struct gtpc_create_session_request create_session_request; struct gtpc_create_session_response create_session_response; + struct gtpc_modify_bearer_request modify_bearer_request; + //struct gtpc_modify_bearer_response modify_bearer_response; } gtpc_msg_choice_t; /**************************************************************************** diff --git a/srsepc/hdr/spgw/spgw.h b/srsepc/hdr/spgw/spgw.h index a9c1b9ba3..2ea2278c8 100644 --- a/srsepc/hdr/spgw/spgw.h +++ b/srsepc/hdr/spgw/spgw.h @@ -53,14 +53,14 @@ typedef struct { } spgw_args_t; -typedef struct { +typedef struct spgw_tunnel_ctx { uint64_t imsi; in_addr_t ue_ipv4; struct srslte::gtpc_f_teid_ie up_ctrl_fteid; struct srslte::gtpc_f_teid_ie up_user_fteid; struct srslte::gtpc_f_teid_ie dw_ctrl_fteid; struct srslte::gtpc_f_teid_ie dw_user_fteid; -} spgw_ue_ctx; +} spgw_tunnel_ctx_t; class spgw: public thread @@ -73,6 +73,7 @@ public: void run_thread(); void handle_create_session_request(struct srslte::gtpc_create_session_request *cs_req, struct srslte::gtpc_pdu *cs_resp_pdu); + void handle_modify_bearer_request(struct srslte::gtpc_pdu *mb_req_pdu, struct srslte::gtpc_pdu *mb_resp_pdu); private: @@ -101,8 +102,8 @@ private: uint64_t m_next_ctrl_teid; uint64_t m_next_user_teid; - std::map m_teid_to_ue_ctx; //Map control TEID to ue_ctx. Usefull to get reply ctrl TEID - std::map m_ip_to_teid; //Map IP to User-plane TEID for downlink traffic + std::map m_teid_to_tunnel_ctx; //Map control TEID to tunnel ctx. Usefull to get reply ctrl TEID, UE IP, etc. + std::map m_ip_to_teid; //Map IP to User-plane TEID for downlink traffic /*Logs*/ srslte::log_filter *m_spgw_log; diff --git a/srsepc/src/mme/mme_gtpc.cc b/srsepc/src/mme/mme_gtpc.cc index 75b811835..8da689f32 100644 --- a/srsepc/src/mme/mme_gtpc.cc +++ b/srsepc/src/mme/mme_gtpc.cc @@ -176,7 +176,7 @@ mme_gtpc::send_modify_bearer_request(erab_ctx_t *erab_ctx) header->teid = sgw_ctrl_fteid->teid; header->type = srslte::GTPC_MSG_TYPE_MODIFY_BEARER_REQUEST; - srslte::gtpc_modify_bearer_request *mb_req = &mb_req_pdu.modify_bearer_request; + srslte::gtpc_modify_bearer_request *mb_req = &mb_req_pdu.choice.modify_bearer_request; mb_req->eps_bearer_context_to_modify.ebi = erab_ctx->erab_id; mb_req->eps_bearer_context_to_modify.s1_u_enb_f_teid.ipv4 = enb_fteid->ipv4; mb_req->eps_bearer_context_to_modify.s1_u_enb_f_teid.teid = enb_fteid->teid; diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index 2f47de745..5a9b7f6c6 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -323,11 +323,11 @@ spgw::handle_create_session_request(struct srslte::gtpc_create_session_request * in_addr_t ue_ip = get_new_ue_ipv4(); //Save the UE IP to User TEID map //TODO!!! - struct sgw_ue_ctx *ue_ctx = new sgw_ue_ctx; - sgw_ue_ctx->imsi = cs_req->imsi; - sgw_ue_ctx->ul_user_fteid.teid = spgw_uplink_user_teid; - sgw_ue_ctx->ul_ctrl_fteid = spgw_uplink_ctrl_teid; - sgw_ue_ctx->ue_ipv4 = ue_ip; + spgw_tunnel_ctx_t *tunnel_ctx = new spgw_tunnel_ctx_t; + tunnel_ctx->imsi = cs_req->imsi; + tunnel_ctx->up_user_fteid.teid = spgw_uplink_user_teid; + tunnel_ctx->up_ctrl_fteid.teid = spgw_uplink_ctrl_teid; + tunnel_ctx->ue_ipv4 = ue_ip; //Create session response message //Setup GTP-C header @@ -363,13 +363,28 @@ spgw::handle_modify_bearer_request(struct srslte::gtpc_pdu *mb_req_pdu, struct s { m_spgw_log->info("Received Modified Bearer Request\n"); - //Get control tunnel info from - //Setting up Modify bearer request PDU + //Get control tunnel info from mb_req PDU + uint32_t ctrl_teid = mb_req_pdu->header.teid; + std::map::iterator tunnel_it = m_teid_to_tunnel_ctx.find(ctrl_teid); + if(tunnel_it == m_teid_to_tunnel_ctx.end()) + { + m_spgw_log->warning("Could not find TEID %d to modify",ctrl_teid); + return; + } + spgw_tunnel_ctx_t *tunnel_ctx = tunnel_it->second; + + //Store user DW link TEID + srslte::gtpc_modify_bearer_request *mb_req = &mb_req_pdu->choice.modify_bearer_request; + tunnel_ctx->dw_user_fteid = mb_req->eps_bearer_context_to_modify.s1_u_enb_f_teid; + //Set up actual tunnel + //TODO!!! + + //Setting up Modify bearer response PDU //Header srslte::gtpc_header *header = &mb_req_pdu->header; header->piggyback = false; header->teid_present = true; - header->teid = ; // + header->teid = tunnel_ctx->dw_ctrl_fteid.teid; // header->type = srslte::GTPC_MSG_TYPE_MODIFY_BEARER_RESPONSE; //PDU From 04d67509cff4b4617bd40871fe82749bb80486df Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 6 Dec 2017 18:34:37 +0000 Subject: [PATCH 114/172] Getting all information necessary at the SP-GW to setup the user tunnels from the modify bearer response. --- lib/include/srslte/asn1/gtpc.h | 2 +- lib/include/srslte/asn1/gtpc_msg.h | 45 +++++++++++++++++++++++++++++- srsepc/epc.conf.example | 2 +- srsepc/hdr/spgw/spgw.h | 2 ++ srsepc/src/mme/mme_gtpc.cc | 7 +++-- srsepc/src/mme/s1ap.cc | 4 +++ srsepc/src/spgw/spgw.cc | 39 ++++++++++++++++++++------ 7 files changed, 87 insertions(+), 14 deletions(-) diff --git a/lib/include/srslte/asn1/gtpc.h b/lib/include/srslte/asn1/gtpc.h index e216bcf12..23a4d7118 100644 --- a/lib/include/srslte/asn1/gtpc.h +++ b/lib/include/srslte/asn1/gtpc.h @@ -75,7 +75,7 @@ typedef union gtpc_msg_choice struct gtpc_create_session_request create_session_request; struct gtpc_create_session_response create_session_response; struct gtpc_modify_bearer_request modify_bearer_request; - //struct gtpc_modify_bearer_response modify_bearer_response; + struct gtpc_modify_bearer_response modify_bearer_response; } gtpc_msg_choice_t; /**************************************************************************** diff --git a/lib/include/srslte/asn1/gtpc_msg.h b/lib/include/srslte/asn1/gtpc_msg.h index 686f9d9ce..efd2a2290 100644 --- a/lib/include/srslte/asn1/gtpc_msg.h +++ b/lib/include/srslte/asn1/gtpc_msg.h @@ -334,5 +334,48 @@ struct gtpc_modify_bearer_request //SGW LDN }; -}; //namespace +/**************************************************************************** + * + * GTP-C v2 Modify Bearer Response + * Ref: 3GPP TS 29.274 v10.14.0 Table 7.2.8-1 + * + ***************************************************************************/ + +struct gtpc_modify_bearer_response +{ + struct gtpc_cause_ie cause; + //MSISDN + //Linked EPS Bearer ID + //APN-AMBR + //APN Restriction + //Protocol Configuration Options + + struct gtpc_bearer_context_modified_ie + { + uint8_t ebi; + struct gtpc_cause_ie cause; + bool s1_u_sgw_f_teid_present; + struct gtpc_f_teid_ie s1_u_sgw_f_teid; + bool s12_sgw_f_teid_present; + struct gtpc_f_teid_ie s12_sgw_f_teid; + bool s4_u_sgw_f_teid_present; + struct gtpc_f_teid_ie s4_u_sgw_f_teid; + //charging id + //bearer flags + } eps_bearer_context_modified; + //Bearer Contexts marked for removal + //Change Reporting action + //CSG information reporting action + //Charging gateway name + //charging gateway address + //P-GW FQ-CSID + //S-GW FQ-CSID + //Recovery + //S-GW LDN + //P-GW LDN + //indication Flags + //ext +}; + +} //namespace #endif //GTPC_V2_MSG_H diff --git a/srsepc/epc.conf.example b/srsepc/epc.conf.example index 053915a1d..1836f8fb8 100644 --- a/srsepc/epc.conf.example +++ b/srsepc/epc.conf.example @@ -22,5 +22,5 @@ mnc = 01 mme_bind_addr = 127.0.0.0/24 [spgw] -gtpu_bind_addr=127.0.0.1 +gtpu_bind_addr=127.0.0.2 sgi_if_addr=172.0.0.1 diff --git a/srsepc/hdr/spgw/spgw.h b/srsepc/hdr/spgw/spgw.h index 2ea2278c8..9b5af5eff 100644 --- a/srsepc/hdr/spgw/spgw.h +++ b/srsepc/hdr/spgw/spgw.h @@ -102,6 +102,8 @@ private: uint64_t m_next_ctrl_teid; uint64_t m_next_user_teid; + sockaddr_in m_s1u_addr; + std::map m_teid_to_tunnel_ctx; //Map control TEID to tunnel ctx. Usefull to get reply ctrl TEID, UE IP, etc. std::map m_ip_to_teid; //Map IP to User-plane TEID for downlink traffic diff --git a/srsepc/src/mme/mme_gtpc.cc b/srsepc/src/mme/mme_gtpc.cc index 8da689f32..a085e5541 100644 --- a/srsepc/src/mme/mme_gtpc.cc +++ b/srsepc/src/mme/mme_gtpc.cc @@ -108,6 +108,7 @@ mme_gtpc::send_create_session_request(uint64_t imsi, uint32_t mme_ue_s1ap_id) cs_req_pdu.header.type = srslte::GTPC_MSG_TYPE_CREATE_SESSION_REQUEST; //Setup GTP-C Create Session Request IEs + cs_req->imsi = imsi; // Control TEID allocated cs_req->sender_f_teid.teid = get_new_ctrl_teid(); cs_req->sender_f_teid.ipv4 = m_mme_gtpc_ip; @@ -171,7 +172,7 @@ mme_gtpc::send_modify_bearer_request(erab_ctx_t *erab_ctx) srslte::gtpc_f_teid_ie *enb_fteid = &erab_ctx->enb_fteid; srslte::gtpc_f_teid_ie *sgw_ctrl_fteid = &erab_ctx->sgw_ctrl_fteid; - srslte::gtpc_header *header = &pdu.header; + srslte::gtpc_header *header = &mb_req_pdu.header; header->teid_present = true; header->teid = sgw_ctrl_fteid->teid; header->type = srslte::GTPC_MSG_TYPE_MODIFY_BEARER_REQUEST; @@ -182,7 +183,9 @@ mme_gtpc::send_modify_bearer_request(erab_ctx_t *erab_ctx) mb_req->eps_bearer_context_to_modify.s1_u_enb_f_teid.teid = enb_fteid->teid; m_mme_gtpc_log->info("GTP-C Modify bearer request -- S-GW Control TEID %d\n", sgw_ctrl_fteid->teid ); - m_mme_gtpc_log->info("GTP-C Modify bearer request -- S1-U TEID 0x%x\n", enb_fteid->teid ); + struct in_addr addr; + addr.s_addr = enb_fteid->ipv4; + m_mme_gtpc_log->info("GTP-C Modify bearer request -- S1-U TEID 0x%x, IP %s\n", enb_fteid->teid, inet_ntoa(addr) ); // srslte::gtpc_pdu mb_resp_pdu; diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index a58ac6a40..27be5ba29 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -674,8 +674,12 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: ue_ctx->erabs_ctx[erab_ctxt->e_RAB_ID.E_RAB_ID].sgw_ctrl_fteid.teid = sgw_ctrl_fteid.teid; ue_ctx->erabs_ctx[erab_ctxt->e_RAB_ID.E_RAB_ID].sgw_ctrl_fteid.ipv4 = sgw_ctrl_fteid.ipv4; + struct in_addr addr; + addr.s_addr = sgw_s1u_ip; m_s1ap_log->info("Sent Intial Context Setup Request. E-RAB id %d \n",erab_ctxt->e_RAB_ID.E_RAB_ID); + m_s1ap_log->info("Initial Context -- S1-U TEID 0x%x. IP %s \n", tmp_teid,inet_ntoa(addr)); m_s1ap_log->console("Sent Intial Context Setup Request, E-RAB id %d\n",erab_ctxt->e_RAB_ID.E_RAB_ID); + m_s1ap_log->console("Initial Context -- S1-U TEID 0x%x. IP %s \n", tmp_teid,inet_ntoa(addr)); m_pool->deallocate(reply_buffer); m_pool->deallocate(nas_buffer); diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index 5a9b7f6c6..6d390ad38 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -220,16 +220,17 @@ spgw::init_s1u(spgw_args_t *args) m_s1u_up = true; //Bind the socket - struct sockaddr_in servaddr; - servaddr.sin_family = AF_INET; - servaddr.sin_addr.s_addr=inet_addr(args->gtpu_bind_addr.c_str()); - servaddr.sin_port=htons(GTPU_RX_PORT); + m_s1u_addr.sin_family = AF_INET; + m_s1u_addr.sin_addr.s_addr=inet_addr(args->gtpu_bind_addr.c_str()); + m_s1u_addr.sin_port=htons(GTPU_RX_PORT); - if (bind(m_s1u,(struct sockaddr *)&servaddr,sizeof(struct sockaddr_in))) { + if (bind(m_s1u,(struct sockaddr *)&m_s1u_addr,sizeof(struct sockaddr_in))) { m_spgw_log->error("Failed to bind socket: %s\n", strerror(errno)); return srslte::ERROR_CANT_START; } m_spgw_log->info("S1-U socket = %d\n", m_s1u); + m_spgw_log->info("S1-U IP = %s, Port = %d \n", inet_ntoa(m_s1u_addr.sin_addr),ntohs(m_s1u_addr.sin_port)); + return srslte::ERROR_NONE; } @@ -326,9 +327,13 @@ spgw::handle_create_session_request(struct srslte::gtpc_create_session_request * spgw_tunnel_ctx_t *tunnel_ctx = new spgw_tunnel_ctx_t; tunnel_ctx->imsi = cs_req->imsi; tunnel_ctx->up_user_fteid.teid = spgw_uplink_user_teid; + tunnel_ctx->up_user_fteid.ipv4 = m_s1u_addr.sin_addr.s_addr; + tunnel_ctx->dw_ctrl_fteid.teid = cs_req->sender_f_teid.teid; + tunnel_ctx->dw_ctrl_fteid.ipv4 = cs_req->sender_f_teid.ipv4; + tunnel_ctx->up_ctrl_fteid.teid = spgw_uplink_ctrl_teid; tunnel_ctx->ue_ipv4 = ue_ip; - + m_teid_to_tunnel_ctx.insert(std::pair(spgw_uplink_ctrl_teid,tunnel_ctx)); //Create session response message //Setup GTP-C header header->piggyback = false; @@ -348,6 +353,7 @@ spgw::handle_create_session_request(struct srslte::gtpc_create_session_request * cs_resp->eps_bearer_context_created.cause.cause_value = srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED; cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid_present=true; cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.teid = spgw_uplink_user_teid; + cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.ipv4 = m_s1u_addr.sin_addr.s_addr; //Fill in the PAA cs_resp->paa_present = true; cs_resp->paa.pdn_type = srslte::GTPC_PDN_TYPE_IPV4; @@ -368,15 +374,30 @@ spgw::handle_modify_bearer_request(struct srslte::gtpc_pdu *mb_req_pdu, struct s std::map::iterator tunnel_it = m_teid_to_tunnel_ctx.find(ctrl_teid); if(tunnel_it == m_teid_to_tunnel_ctx.end()) { - m_spgw_log->warning("Could not find TEID %d to modify",ctrl_teid); + m_spgw_log->warning("Could not find TEID %d to modify\n",ctrl_teid); return; } spgw_tunnel_ctx_t *tunnel_ctx = tunnel_it->second; //Store user DW link TEID srslte::gtpc_modify_bearer_request *mb_req = &mb_req_pdu->choice.modify_bearer_request; - tunnel_ctx->dw_user_fteid = mb_req->eps_bearer_context_to_modify.s1_u_enb_f_teid; + tunnel_ctx->dw_user_fteid.teid = mb_req->eps_bearer_context_to_modify.s1_u_enb_f_teid.teid; + tunnel_ctx->dw_user_fteid.ipv4 = mb_req->eps_bearer_context_to_modify.s1_u_enb_f_teid.ipv4; //Set up actual tunnel + m_spgw_log->info("Setting Up GTP-U tunnel. Tunnel info: \n"); + struct in_addr addr; + addr.s_addr = tunnel_ctx->ue_ipv4; + m_spgw_log->info("IMSI: %lu, UE IP, %s \n",tunnel_ctx->imsi, inet_ntoa(addr)); + m_spgw_log->info("S-GW Rx Ctrl TEID 0x%x, MME Rx Ctrl TEID 0x%x\n", tunnel_ctx->up_ctrl_fteid.teid, tunnel_ctx->dw_ctrl_fteid.teid); + m_spgw_log->info("S-GW Rx Ctrl IP (NA), MME Rx Ctrl IP (NA)\n"); + + struct in_addr addr2; + addr2.s_addr = tunnel_ctx->up_user_fteid.ipv4; + m_spgw_log->info("S-GW Rx User TEID 0x%x, S-GW Rx User IP %s\n", tunnel_ctx->up_user_fteid.teid, inet_ntoa(addr2)); + + struct in_addr addr3; + addr3.s_addr = tunnel_ctx->dw_user_fteid.ipv4; + m_spgw_log->info("eNB Rx User TEID 0x%x, eNB Rx User IP %s\n", tunnel_ctx->dw_user_fteid.teid, inet_ntoa(addr3)); //TODO!!! //Setting up Modify bearer response PDU @@ -388,6 +409,6 @@ spgw::handle_modify_bearer_request(struct srslte::gtpc_pdu *mb_req_pdu, struct s header->type = srslte::GTPC_MSG_TYPE_MODIFY_BEARER_RESPONSE; //PDU - srslte::gtpc_modify_bearer_response *mb_resp = mb_req_pdu.choice.modify_bearer_response; + srslte::gtpc_modify_bearer_response *mb_resp = &mb_req_pdu->choice.modify_bearer_response; } } //namespace srsepc From d18ff13d2796c82f523eb96a780884daf579ca8a Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 6 Dec 2017 20:18:11 +0000 Subject: [PATCH 115/172] Modify Bearer response parsed ok. Starting to setup the user-plane tunnels --- srsepc/hdr/mme/mme_gtpc.h | 1 + srsepc/hdr/mme/s1ap.h | 2 ++ srsepc/hdr/spgw/spgw.h | 1 + srsepc/src/mme/mme_gtpc.cc | 23 ++++++++++++++++++++++- srsepc/src/mme/s1ap.cc | 20 ++++++++++++++++++++ srsepc/src/spgw/spgw.cc | 14 ++++++++++---- 6 files changed, 56 insertions(+), 5 deletions(-) diff --git a/srsepc/hdr/mme/mme_gtpc.h b/srsepc/hdr/mme/mme_gtpc.h index f41863698..2c4cb10c9 100644 --- a/srsepc/hdr/mme/mme_gtpc.h +++ b/srsepc/hdr/mme/mme_gtpc.h @@ -51,6 +51,7 @@ public: void send_create_session_request(uint64_t imsi, uint32_t mme_s1ap_id); void handle_create_session_response(srslte::gtpc_pdu *cs_resp_pdu); void send_modify_bearer_request(erab_ctx_t *bearer_ctx); + void handle_modify_bearer_response(srslte::gtpc_pdu *mb_resp_pdu); private: diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 0d0f0a598..ee5e5e6d1 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -87,6 +87,8 @@ public: bool handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *in_ctxt_resp); bool handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx); + void activate_eps_bearer(uint32_t mme_s1ap_id, uint8_t ebi); + void print_enb_ctx_info(const enb_ctx_t &enb_ctx); private: diff --git a/srsepc/hdr/spgw/spgw.h b/srsepc/hdr/spgw/spgw.h index 9b5af5eff..62fd704d2 100644 --- a/srsepc/hdr/spgw/spgw.h +++ b/srsepc/hdr/spgw/spgw.h @@ -56,6 +56,7 @@ typedef struct { typedef struct spgw_tunnel_ctx { uint64_t imsi; in_addr_t ue_ipv4; + uint8_t ebi; struct srslte::gtpc_f_teid_ie up_ctrl_fteid; struct srslte::gtpc_f_teid_ie up_user_fteid; struct srslte::gtpc_f_teid_ie dw_ctrl_fteid; diff --git a/srsepc/src/mme/mme_gtpc.cc b/srsepc/src/mme/mme_gtpc.cc index a085e5541..4d7a0aee9 100644 --- a/srsepc/src/mme/mme_gtpc.cc +++ b/srsepc/src/mme/mme_gtpc.cc @@ -189,6 +189,27 @@ mme_gtpc::send_modify_bearer_request(erab_ctx_t *erab_ctx) // srslte::gtpc_pdu mb_resp_pdu; - m_spgw->handle_modify_bearer_request(&mb_req_pdu,&mb_resp_pdu); + m_spgw->handle_modify_bearer_request(&mb_req_pdu,&mb_resp_pdu); + handle_modify_bearer_response(&mb_resp_pdu); + return; } + +void +mme_gtpc::handle_modify_bearer_response(srslte::gtpc_pdu *mb_resp_pdu) +{ + uint32_t mme_ctrl_teid = mb_resp_pdu->header.teid; + std::map::iterator mme_s1ap_id_it = m_teid_to_mme_s1ap_id.find(mme_ctrl_teid); + if(mme_s1ap_id_it == m_teid_to_mme_s1ap_id.end()) + { + m_mme_gtpc_log->error("Could not find MME S1AP Id from control TEID\n"); + return; + } + + uint8_t ebi = mb_resp_pdu->choice.modify_bearer_response.eps_bearer_context_modified.ebi; + m_mme_gtpc_log->debug("Activating EPS bearer with id %d\n", ebi); + m_s1ap->activate_eps_bearer(mme_s1ap_id_it->second,ebi); + + return; +} + } //namespace srsepc diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 27be5ba29..370ed87c2 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -823,6 +823,26 @@ s1ap::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQU return true; } +void +s1ap::activate_eps_bearer(uint32_t mme_s1ap_id, uint8_t ebi) +{ + std::map::iterator ue_ctx_it = m_active_ues.find(mme_s1ap_id); + if(ue_ctx_it == m_active_ues.end()) + { + m_s1ap_log->error("Could not find UE context\n"); + return; + } + ue_ctx_t * ue_ctx = ue_ctx_it->second; + if (ue_ctx->erabs_ctx[ebi].state != ERAB_CTX_REQUESTED) + { + m_s1ap_log->error("EPS Bearer could not be activated. EPS Bearer id %d\n",ebi); + return; + } + + ue_ctx->erabs_ctx[ebi].state = ERAB_ACTIVE; + m_s1ap_log->info("Activated EPS Bearer\n"); + return; +} void s1ap::print_enb_ctx_info(const enb_ctx_t &enb_ctx) diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index 6d390ad38..ef301d064 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -323,14 +323,16 @@ spgw::handle_create_session_request(struct srslte::gtpc_create_session_request * //Allocate UE IP in_addr_t ue_ip = get_new_ue_ipv4(); + uint8_t default_bearer_id = 5; //Save the UE IP to User TEID map //TODO!!! spgw_tunnel_ctx_t *tunnel_ctx = new spgw_tunnel_ctx_t; tunnel_ctx->imsi = cs_req->imsi; + tunnel_ctx->ebi = default_bearer_id; tunnel_ctx->up_user_fteid.teid = spgw_uplink_user_teid; tunnel_ctx->up_user_fteid.ipv4 = m_s1u_addr.sin_addr.s_addr; tunnel_ctx->dw_ctrl_fteid.teid = cs_req->sender_f_teid.teid; tunnel_ctx->dw_ctrl_fteid.ipv4 = cs_req->sender_f_teid.ipv4; - + tunnel_ctx->up_ctrl_fteid.teid = spgw_uplink_ctrl_teid; tunnel_ctx->ue_ipv4 = ue_ip; m_teid_to_tunnel_ctx.insert(std::pair(spgw_uplink_ctrl_teid,tunnel_ctx)); @@ -349,7 +351,7 @@ spgw::handle_create_session_request(struct srslte::gtpc_create_session_request * cs_resp->sender_f_teid.teid = spgw_uplink_ctrl_teid; cs_resp->sender_f_teid.ipv4 = 0;//FIXME This is not relevant, as the GTP-C is not transmitted over sockets yet. //Bearer context created - cs_resp->eps_bearer_context_created.ebi = 5; + cs_resp->eps_bearer_context_created.ebi = default_bearer_id; cs_resp->eps_bearer_context_created.cause.cause_value = srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED; cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid_present=true; cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.teid = spgw_uplink_user_teid; @@ -402,13 +404,17 @@ spgw::handle_modify_bearer_request(struct srslte::gtpc_pdu *mb_req_pdu, struct s //Setting up Modify bearer response PDU //Header - srslte::gtpc_header *header = &mb_req_pdu->header; + srslte::gtpc_header *header = &mb_resp_pdu->header; header->piggyback = false; header->teid_present = true; header->teid = tunnel_ctx->dw_ctrl_fteid.teid; // header->type = srslte::GTPC_MSG_TYPE_MODIFY_BEARER_RESPONSE; //PDU - srslte::gtpc_modify_bearer_response *mb_resp = &mb_req_pdu->choice.modify_bearer_response; + srslte::gtpc_modify_bearer_response *mb_resp = &mb_resp_pdu->choice.modify_bearer_response; + mb_resp->cause.cause_value = srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED; + mb_resp->eps_bearer_context_modified.ebi = tunnel_ctx->ebi; + printf("%d %d\n",mb_resp->eps_bearer_context_modified.ebi, tunnel_ctx->ebi); + mb_resp->eps_bearer_context_modified.cause.cause_value = srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED; } } //namespace srsepc From 2b7bd546bc749693300dec327071682418853fd3 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 7 Dec 2017 15:06:24 +0000 Subject: [PATCH 116/172] Able to find eNB F-TEID from destination IP. Starting to add the GTP-U header to the packet. --- srsepc/hdr/spgw/spgw.h | 3 +++ srsepc/src/spgw/spgw.cc | 52 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/srsepc/hdr/spgw/spgw.h b/srsepc/hdr/spgw/spgw.h index 62fd704d2..d39e6a6ba 100644 --- a/srsepc/hdr/spgw/spgw.h +++ b/srsepc/hdr/spgw/spgw.h @@ -76,6 +76,8 @@ public: void handle_create_session_request(struct srslte::gtpc_create_session_request *cs_req, struct srslte::gtpc_pdu *cs_resp_pdu); void handle_modify_bearer_request(struct srslte::gtpc_pdu *mb_req_pdu, struct srslte::gtpc_pdu *mb_resp_pdu); + void handle_sgi_pdu(srslte::byte_buffer_t *msg); + private: spgw(); @@ -105,6 +107,7 @@ private: sockaddr_in m_s1u_addr; + pthread_mutex_t m_mutex; std::map m_teid_to_tunnel_ctx; //Map control TEID to tunnel ctx. Usefull to get reply ctrl TEID, UE IP, etc. std::map m_ip_to_teid; //Map IP to User-plane TEID for downlink traffic diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index ef301d064..fcde590da 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -104,6 +104,9 @@ spgw::init(spgw_args_t* args, srslte::log_filter *spgw_log) m_spgw_log->console("Could not initialize the S1-U interface.\n"); return -1; } + + //Init mutex + pthread_mutex_init(&m_mutex,NULL); m_spgw_log->info("SP-GW Initialized.\n"); m_spgw_log->console("SP-GW Initialized.\n"); return 0; @@ -278,6 +281,7 @@ spgw::run_thread() msg->N_bytes = read(sgi, msg->msg, SRSLTE_MAX_BUFFER_SIZE_BYTES); //m_spgw_log->console("Received PDU from SGi. Bytes %d\n", msg->N_bytes); //m_spgw_log->debug("Received PDU from SGi. Bytes %d\n", msg->N_bytes); + handle_sgi_pdu(msg); } } else @@ -289,6 +293,48 @@ spgw::run_thread() return; } +void +spgw::handle_sgi_pdu(srslte::byte_buffer_t *msg) +{ + uint8_t version=0; + uint32_t dest_ip; + struct in_addr dest_addr; + std::map::iterator gtp_fteid_it; + bool ip_found = false; + srslte::gtpc_f_teid_ie enb_fteid; + + version = msg->msg[0]>>4; + ((uint8_t*)&dest_ip)[0] = msg->msg[16]; + ((uint8_t*)&dest_ip)[1] = msg->msg[17]; + ((uint8_t*)&dest_ip)[2] = msg->msg[18]; + ((uint8_t*)&dest_ip)[3] = msg->msg[19]; + + dest_addr.s_addr = dest_ip; + + m_spgw_log->console("IP version: %d\n", version); + m_spgw_log->console("Received packet to IP: %s\n", inet_ntoa(dest_addr)); + + pthread_mutex_lock(&m_mutex); + gtp_fteid_it = m_ip_to_teid.find(dest_ip); + if(gtp_fteid_it != m_ip_to_teid.end()) + { + ip_found = true; + enb_fteid = gtp_fteid_it->second; + } + pthread_mutex_unlock(&m_mutex); + + if(ip_found == false) + { + m_spgw_log->console("IP Packet is not for any UE\n"); + return; + } + struct in_addr enb_addr; + enb_addr.s_addr = enb_fteid.ipv4; + m_spgw_log->console("UE F-TEID found, TEID 0x%x, eNB IP %s\n", enb_fteid.teid, inet_ntoa(enb_addr)); + + + return; +} uint64_t spgw::get_new_ctrl_teid() @@ -400,7 +446,11 @@ spgw::handle_modify_bearer_request(struct srslte::gtpc_pdu *mb_req_pdu, struct s struct in_addr addr3; addr3.s_addr = tunnel_ctx->dw_user_fteid.ipv4; m_spgw_log->info("eNB Rx User TEID 0x%x, eNB Rx User IP %s\n", tunnel_ctx->dw_user_fteid.teid, inet_ntoa(addr3)); - //TODO!!! + + //Setup IP to F-TEID map + pthread_mutex_lock(&m_mutex); + m_ip_to_teid.insert(std::pair(tunnel_ctx->ue_ipv4, tunnel_ctx->dw_user_fteid)); + pthread_mutex_unlock(&m_mutex); //Setting up Modify bearer response PDU //Header From c838758db236844e59db9cdb75efed2639eac90a Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 7 Dec 2017 17:09:31 +0000 Subject: [PATCH 117/172] Added downlink IP tunnel. Downlink user plane packets reach the UE. --- lib/include/srslte/upper/gtpu.h | 95 ++++++++++++++++++++++++++++++++ lib/src/upper/gtpu.cc | 96 +++++++++++++++++++++++++++++++++ srsepc/src/mme/s1ap.cc | 2 +- srsepc/src/spgw/spgw.cc | 33 ++++++++++-- 4 files changed, 220 insertions(+), 6 deletions(-) create mode 100644 lib/include/srslte/upper/gtpu.h create mode 100644 lib/src/upper/gtpu.cc diff --git a/lib/include/srslte/upper/gtpu.h b/lib/include/srslte/upper/gtpu.h new file mode 100644 index 000000000..3cd8a1202 --- /dev/null +++ b/lib/include/srslte/upper/gtpu.h @@ -0,0 +1,95 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of the srsLTE library. + * + * srsUE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsUE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#ifndef SRSLTE_GTPU_H +#define SRSLTE_GTPU_H + +#include +#include "srslte/common/common.h" + +namespace srslte { + +/**************************************************************************** + * GTPU Header + * Ref: 3GPP TS 29.281 v10.1.0 Section 5 + * + * | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | + * + * 1 | Version |PT | * | E | S |PN | + * 2 | Message Type | + * 3 | Length (1st Octet) | + * 4 | Length (2nd Octet) | + * 5 | TEID (1st Octet) | + * 6 | TEID (2nd Octet) | + * 7 | TEID (3rd Octet) | + * 8 | TEID (4th Octet) | + ***************************************************************************/ + +#define GTPU_HEADER_LEN 8 + +typedef struct{ + uint8_t flags; // Only support 0x30 - v1, PT1 (GTP), no other flags + uint8_t message_type; // Only support 0xFF - T-PDU type + uint16_t length; + uint32_t teid; +}gtpu_header_t; + + +bool gtpu_read_header(srslte::byte_buffer_t *pdu, gtpu_header_t *header); +bool gtpu_write_header(gtpu_header_t *header, srslte::byte_buffer_t *pdu); + +inline void uint8_to_uint32(uint8_t *buf, uint32_t *i) +{ + *i = (uint32_t)buf[0] << 24 | + (uint32_t)buf[1] << 16 | + (uint32_t)buf[2] << 8 | + (uint32_t)buf[3]; +} + +inline void uint32_to_uint8(uint32_t i, uint8_t *buf) +{ + buf[0] = (i >> 24) & 0xFF; + buf[1] = (i >> 16) & 0xFF; + buf[2] = (i >> 8) & 0xFF; + buf[3] = i & 0xFF; +} + +inline void uint8_to_uint16(uint8_t *buf, uint16_t *i) +{ + *i = (uint32_t)buf[0] << 8 | + (uint32_t)buf[1]; +} + +inline void uint16_to_uint8(uint16_t i, uint8_t *buf) +{ + buf[0] = (i >> 8) & 0xFF; + buf[1] = i & 0xFF; +} + + +}//namespace + +#endif diff --git a/lib/src/upper/gtpu.cc b/lib/src/upper/gtpu.cc new file mode 100644 index 000000000..668af8915 --- /dev/null +++ b/lib/src/upper/gtpu.cc @@ -0,0 +1,96 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of the srsLTE library. + * + * srsUE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsUE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + + +#include "srslte/upper/gtpu.h" + + +namespace srslte { + +/**************************************************************************** + * Header pack/unpack helper functions + * Ref: 3GPP TS 29.281 v10.1.0 Section 5 + ***************************************************************************/ + +bool gtpu_write_header(gtpu_header_t *header, srslte::byte_buffer_t *pdu) +{ + if(header->flags != 0x30) { + //gtpu_log->error("gtpu_write_header - Unhandled header flags: 0x%x\n", header->flags); + return false; + } + if(header->message_type != 0xFF) { + //gtpu_log->error("gtpu_write_header - Unhandled message type: 0x%x\n", header->message_type); + return false; + } + if(pdu->get_headroom() < GTPU_HEADER_LEN) { + //gtpu_log->error("gtpu_write_header - No room in PDU for header\n"); + return false; + } + + pdu->msg -= GTPU_HEADER_LEN; + pdu->N_bytes += GTPU_HEADER_LEN; + + uint8_t *ptr = pdu->msg; + + *ptr = header->flags; + ptr++; + *ptr = header->message_type; + ptr++; + uint16_to_uint8(header->length, ptr); + ptr += 2; + uint32_to_uint8(header->teid, ptr); + + return true; +} + +bool gtpu_read_header(srslte::byte_buffer_t *pdu, gtpu_header_t *header) +{ + uint8_t *ptr = pdu->msg; + + pdu->msg += GTPU_HEADER_LEN; + pdu->N_bytes -= GTPU_HEADER_LEN; + + header->flags = *ptr; + ptr++; + header->message_type = *ptr; + ptr++; + uint8_to_uint16(ptr, &header->length); + ptr += 2; + uint8_to_uint32(ptr, &header->teid); + + if(header->flags != 0x30) { + //gtpu_log->error("gtpu_read_header - Unhandled header flags: 0x%x\n", header->flags); + return false; + } + if(header->message_type != 0xFF) { + //gtpu_log->error("gtpu_read_header - Unhandled message type: 0x%x\n", header->message_type); + return false; + } + + return true; +} + +} // namespace srslte diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 370ed87c2..4cef13cab 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -698,7 +698,7 @@ s1ap::handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSE m_s1ap_log->error("Could not find UE's context in active UE's map\n"); return false; } - for(uint32_t i; iE_RABSetupListCtxtSURes.len;i++) + for(uint32_t i=0; iE_RABSetupListCtxtSURes.len;i++) { uint8_t erab_id = in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].e_RAB_ID.E_RAB_ID; erab_ctx_t *erab_ctx = &ue_ctx_it->second->erabs_ctx[erab_id]; diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index fcde590da..d31cf6832 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -35,7 +35,7 @@ #include #include "spgw/spgw.h" #include "mme/mme_gtpc.h" - +#include "srslte/upper/gtpu.h" namespace srsepc{ @@ -263,7 +263,7 @@ spgw::run_thread() //m_spgw_log->info("Waiting for S1-U or SGi packets.\n"); int n = select(max_fd+1, &set, NULL, NULL, NULL); if (n == -1) - { + { m_spgw_log->error("Error from select\n"); } else if (n) @@ -328,11 +328,34 @@ spgw::handle_sgi_pdu(srslte::byte_buffer_t *msg) m_spgw_log->console("IP Packet is not for any UE\n"); return; } - struct in_addr enb_addr; - enb_addr.s_addr = enb_fteid.ipv4; - m_spgw_log->console("UE F-TEID found, TEID 0x%x, eNB IP %s\n", enb_fteid.teid, inet_ntoa(enb_addr)); + struct sockaddr_in enb_addr; + enb_addr.sin_family = AF_INET; + enb_addr.sin_port = htons(GTPU_RX_PORT); + enb_addr.sin_addr.s_addr = enb_fteid.ipv4; + m_spgw_log->console("UE F-TEID found, TEID 0x%x, eNB IP %s\n", enb_fteid.teid, inet_ntoa(enb_addr.sin_addr)); + + //Setup GTP-U header + srslte::gtpu_header_t header; + header.flags = 0x30; + header.message_type = 0xFF; + header.length = msg->N_bytes; + header.teid = enb_fteid.teid; + + //Write header into packet + if(!srslte::gtpu_write_header(&header, msg)) + { + m_spgw_log->console("Error writing GTP-U header on PDU\n"); + } + //Send packet to destination + int n = sendto(m_s1u,msg->msg,msg->N_bytes,0,(struct sockaddr*) &enb_addr,sizeof(enb_addr)); + if(n<0) + { + m_spgw_log->console("Error sending packet to eNB\n"); + return; + } + m_spgw_log->console("Sent packet to %s:%d. Bytes=%d\n",inet_ntoa(enb_addr.sin_addr), GTPU_RX_PORT,n); return; } From c183ac509dd881a1590c6cf7be22400af1f0061e Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 7 Dec 2017 18:34:05 +0000 Subject: [PATCH 118/172] Fixed endianess bug of S-GW address sent to eNB. S-GW now receives upstream user traffic. Starting to strip the gtp-u header. --- srsepc/hdr/spgw/spgw.h | 1 + srsepc/src/mme/s1ap.cc | 2 +- srsepc/src/spgw/spgw.cc | 8 ++++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/srsepc/hdr/spgw/spgw.h b/srsepc/hdr/spgw/spgw.h index d39e6a6ba..00d2ebd12 100644 --- a/srsepc/hdr/spgw/spgw.h +++ b/srsepc/hdr/spgw/spgw.h @@ -77,6 +77,7 @@ public: void handle_modify_bearer_request(struct srslte::gtpc_pdu *mb_req_pdu, struct srslte::gtpc_pdu *mb_resp_pdu); void handle_sgi_pdu(srslte::byte_buffer_t *msg); + void handle_s1u_pdu(srslte::byte_buffer_t *msg); private: diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 4cef13cab..a6bd64faf 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -626,7 +626,7 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: return false; } erab_ctxt->transportLayerAddress.n_bits = 32; //IPv4 - uint32_t sgw_s1u_ip = cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.ipv4; + uint32_t sgw_s1u_ip = htonl(cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.ipv4); uint8_t *tmp_ptr = erab_ctxt->transportLayerAddress.buffer; liblte_value_2_bits(sgw_s1u_ip, &tmp_ptr, 32);//FIXME consider ipv6 diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index d31cf6832..02e5dfd18 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -274,6 +274,7 @@ spgw::run_thread() msg->N_bytes = recvfrom(m_s1u, msg->msg, SRSLTE_MAX_BUFFER_SIZE_BYTES, 0, &src_addr, &addrlen ); //m_spgw_log->console("Received PDU from S1-U. Bytes %d\n", msg->N_bytes); //m_spgw_log->debug("Received PDU from S1-U. Bytes %d\n", msg->N_bytes); + handle_s1u_pdu(msg); } if (FD_ISSET(m_sgi_if, &set)) { @@ -359,6 +360,13 @@ spgw::handle_sgi_pdu(srslte::byte_buffer_t *msg) return; } + +void +spgw::handle_s1u_pdu(srslte::byte_buffer_t *msg) +{ + m_spgw_log->console("Received PDU from S1-U. Bytes=%d\n",msg->N_bytes); + return; +} uint64_t spgw::get_new_ctrl_teid() { From 0a4e256fec4d3378ebf40d8e40f443b4a8c51399 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 7 Dec 2017 19:07:13 +0000 Subject: [PATCH 119/172] Stripping GTP-U header at the S-GW and writting it to the TUN SGi interface. First over-the-air ping between the SP-GW and the UE. --- srsepc/src/spgw/spgw.cc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index 02e5dfd18..a69ff04d5 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -365,6 +365,19 @@ void spgw::handle_s1u_pdu(srslte::byte_buffer_t *msg) { m_spgw_log->console("Received PDU from S1-U. Bytes=%d\n",msg->N_bytes); + srslte::gtpu_header_t header; + srslte::gtpu_read_header(msg, &header); + + m_spgw_log->console("TEID 0x%x. Bytes=%d\n", header.teid, msg->N_bytes); + int n = write(m_sgi_if, msg->msg, msg->N_bytes); + if(n<0) + { + m_spgw_log->error("Could not write to TUN interface.\n",n); + } + else + { + m_spgw_log->console("Forwarded packet to TUN interface\n"); + } return; } uint64_t From aef328d68bca957c27d324d9c3c3a60e984d6c65 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 13 Dec 2017 19:50:19 +0000 Subject: [PATCH 120/172] Added the ability to the HSS to be configured through a .csv. --- srsepc/epc.conf.example | 17 +++++++ srsepc/hdr/hss/hss.h | 23 +++++++-- srsepc/src/hss/hss.cc | 105 ++++++++++++++++++++++++++++++++++++---- srsepc/src/main.cc | 3 ++ srsepc/src/mme/s1ap.cc | 6 ++- srsepc/user_db.csv | 13 +++++ 6 files changed, 152 insertions(+), 15 deletions(-) create mode 100644 srsepc/user_db.csv diff --git a/srsepc/epc.conf.example b/srsepc/epc.conf.example index 1836f8fb8..544e153d1 100644 --- a/srsepc/epc.conf.example +++ b/srsepc/epc.conf.example @@ -21,6 +21,23 @@ mcc = 001 mnc = 01 mme_bind_addr = 127.0.0.0/24 +##################################################################### +# HSS configuration +# +# db_file: Location of .csv file that stores UEs information. +# +##################################################################### +[hss] +db_file = user_db.csv + + +##################################################################### +# SP-GW configuration +# +# gtpu_bind_addr: Location of .csv file that stores UEs information. +# +##################################################################### + [spgw] gtpu_bind_addr=127.0.0.2 sgi_if_addr=172.0.0.1 diff --git a/srsepc/hdr/hss/hss.h b/srsepc/hdr/hss/hss.h index f8a23809d..06ca26842 100644 --- a/srsepc/hdr/hss/hss.h +++ b/srsepc/hdr/hss/hss.h @@ -38,14 +38,22 @@ #include "srslte/common/logger_file.h" #include "srslte/common/log_filter.h" #include "srslte/common/buffer_pool.h" - +#include namespace srsepc{ typedef struct{ - std::string ue_file; + std::string db_file; }hss_args_t; +typedef struct{ + std::string name; + uint64_t imsi; + uint8_t key[16]; + uint8_t op[16]; + uint8_t amf[2]; +}hss_ue_ctx_t; + class hss @@ -54,12 +62,16 @@ public: static hss* get_instance(void); static void cleanup(void); int init(hss_args_t *hss_args, srslte::log_filter* hss_log); - + bool read_db_file(std::string db_file); + void get_sqn(uint8_t sqn[6]); void gen_rand(uint8_t rand_[16]); bool get_k_amf_op(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op); bool gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres); - + + std::vector split_string(const std::string &str, char delimiter); + void get_uint_vec_from_hex_str(const std::string &key_str, uint8_t *key, uint len); + private: hss(); @@ -68,6 +80,9 @@ private: uint64_t m_sqn; //48 bits srslte::byte_buffer_pool *m_pool; + std::ifstream m_db_file; + + std::map m_imsi_to_ue_ctx; /*Logs*/ srslte::log_filter *m_hss_log; diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index 98058b77b..32bc1d54d 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -41,12 +41,16 @@ boost::mutex hss_instance_mutex; hss::hss() :m_sqn(0x112233445566) { - m_pool = srslte::byte_buffer_pool::get_instance(); + m_pool = srslte::byte_buffer_pool::get_instance(); return; } hss::~hss() { + if(m_db_file.is_open()) + { + m_db_file.close(); + } return; } @@ -73,15 +77,57 @@ hss::cleanup(void) int hss::init(hss_args_t *hss_args, srslte::log_filter *hss_log) { - /*Init loggers*/ srand(time(NULL)); - + /*Init loggers*/ m_hss_log = hss_log; m_hss_log->info("HSS Initialized\n"); m_hss_log->console("HSS Initialized\n"); + + /*Read user information from DB*/ + read_db_file(hss_args->db_file); return 0; } +bool +hss::read_db_file(std::string db_filename) +{ + m_db_file.open(db_filename.c_str()); + if(!m_db_file.is_open()) + { + return false; + } + m_hss_log->info("Opended DB file: %s\n", db_filename.c_str() ); + + std::string line; + while (std::getline(m_db_file, line)) + { + if(line[0] != '#') + { + std::vector split = split_string(line,','); + if(split.size()!=5) + { + m_hss_log->error("Error parsing .csv file %d\n"); + return false; + } + hss_ue_ctx_t *ue_ctx = new hss_ue_ctx_t; + ue_ctx->name = split[0]; + ue_ctx->imsi = atoll(split[1].c_str()); + get_uint_vec_from_hex_str(split[2],ue_ctx->key,16); + get_uint_vec_from_hex_str(split[3],ue_ctx->op,16); + get_uint_vec_from_hex_str(split[4],ue_ctx->amf,2); + + m_hss_log->debug("Added user from DB, IMSI: %015lu\n", ue_ctx->imsi); + m_hss_log->debug_hex(ue_ctx->key, 16, "User Key : "); + m_hss_log->debug_hex(ue_ctx->op, 16, "User OP : "); + m_hss_log->debug_hex(ue_ctx->amf, 2, "AMF : "); + + m_imsi_to_ue_ctx.insert(std::pair(ue_ctx->imsi,ue_ctx)); + } + } + + return true; +} + bool hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres) { @@ -154,22 +200,24 @@ bool hss::get_k_amf_op(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op ) { + /* uint8_t k_tmp[16] ={0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff}; uint8_t amf_tmp[2]={0x80,0x00}; uint8_t op_tmp[16]={0x63,0xbf,0xA5,0x0E,0xE6,0x52,0x33,0x65,0xFF,0x14,0xC1,0xF4,0x5F,0x88,0x73,0x7D}; - - if(imsi != 1010123456789) + */ + std::map::iterator ue_ctx_it = m_imsi_to_ue_ctx.find(imsi); + if(ue_ctx_it == m_imsi_to_ue_ctx.end()) { m_hss_log->info("User not found. IMSI: %015lu\n",imsi); m_hss_log->console("User not found. IMSI: %015lu\n",imsi); return false; } - + hss_ue_ctx_t *ue_ctx = ue_ctx_it->second; m_hss_log->info("Found User %015lu\n",imsi); m_hss_log->console("Found User %015lu\n",imsi); - memcpy(k,k_tmp,16); - memcpy(amf,amf_tmp,2); - memcpy(op,op_tmp,16); + memcpy(k,ue_ctx->key,16); + memcpy(amf,ue_ctx->amf,2); + memcpy(op,ue_ctx->op,16); return true; } @@ -195,4 +243,43 @@ hss::gen_rand(uint8_t rand_[16]) return; } +/* Helper functions*/ +std::vector +hss::split_string(const std::string &str, char delimiter) +{ + std::vector tokens; + std::string token; + std::istringstream tokenStream(str); + + while (std::getline(tokenStream, token, delimiter)) + { + tokens.push_back(token); + } + return tokens; +} + +void +hss::get_uint_vec_from_hex_str(const std::string &key_str, uint8_t *key, uint len) +{ + const char *pos = key_str.c_str(); + + for (uint count = 0; count < len; count++) { + sscanf(pos, "%2hhx", &key[count]); + pos += 2; + } + + return; +} + + /* +uint64_t +string_to_imsi() +{ + uint64_t imsi = 0; + for(int i=0;i<=14;i++){ + imsi += attach_req.eps_mobile_id.imsi[i]*std::pow(10,14-i); + } + return imsi; +} + */ } //namespace srsepc diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index b75fcd32d..5db3235fa 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -73,6 +73,7 @@ parse_args(all_args_t *args, int argc, char* argv[]) { string mme_bind_addr; string spgw_bind_addr; string sgi_if_addr; + string hss_db_file; // Command line only options bpo::options_description general("General options"); @@ -92,6 +93,7 @@ parse_args(all_args_t *args, int argc, char* argv[]) { ("mme.mcc", bpo::value(&mcc)->default_value("001"), "Mobile Country Code") ("mme.mnc", bpo::value(&mnc)->default_value("01"), "Mobile Network Code") ("mme.mme_bind_addr", bpo::value(&mme_bind_addr)->default_value("127.0.0.1"),"IP address of MME for S1 connnection") + ("hss.db_file", bpo::value(&hss_db_file)->default_value("ue_db.csv"),".csv file that stores UE's keys") ("spgw.gtpu_bind_addr", bpo::value(&spgw_bind_addr)->default_value("127.0.0.1"),"IP address of SP-GW for the S1-U connection") ("spgw.sgi_if_addr", bpo::value(&sgi_if_addr)->default_value("176.16.0.1"),"IP address of TUN interface for the SGi connection") ; @@ -168,6 +170,7 @@ parse_args(all_args_t *args, int argc, char* argv[]) { args->mme_args.s1ap_args.mme_bind_addr = mme_bind_addr; args->spgw_args.gtpu_bind_addr = spgw_bind_addr; args->spgw_args.sgi_if_addr = sgi_if_addr; + args->hss_args.db_file = hss_db_file; return; } diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index a6bd64faf..370d7318a 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -627,6 +627,7 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: } erab_ctxt->transportLayerAddress.n_bits = 32; //IPv4 uint32_t sgw_s1u_ip = htonl(cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.ipv4); + //uint32_t sgw_s1u_ip = cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.ipv4; uint8_t *tmp_ptr = erab_ctxt->transportLayerAddress.buffer; liblte_value_2_bits(sgw_s1u_ip, &tmp_ptr, 32);//FIXME consider ipv6 @@ -833,9 +834,10 @@ s1ap::activate_eps_bearer(uint32_t mme_s1ap_id, uint8_t ebi) return; } ue_ctx_t * ue_ctx = ue_ctx_it->second; - if (ue_ctx->erabs_ctx[ebi].state != ERAB_CTX_REQUESTED) + if (ue_ctx->erabs_ctx[ebi].state != ERAB_CTX_SETUP) { - m_s1ap_log->error("EPS Bearer could not be activated. EPS Bearer id %d\n",ebi); + m_s1ap_log->error("EPS Bearer could not be activated. MME S1AP Id %d, EPS Bearer id %d, state %d\n",mme_s1ap_id,ebi,ue_ctx->erabs_ctx[ebi].state); + m_s1ap_log->console("EPS Bearer could not be activated. MME S1AP Id %d, EPS Bearer id %d\n",mme_s1ap_id,ebi,ue_ctx->erabs_ctx[ebi].state); return; } diff --git a/srsepc/user_db.csv b/srsepc/user_db.csv new file mode 100644 index 000000000..f306adaa3 --- /dev/null +++ b/srsepc/user_db.csv @@ -0,0 +1,13 @@ +# +# .csv to store UE's information in HSS +# Kept in the following format: "Name,IMSI,Key,OP,AMF" +# +# Name: Human readable name to help distinguish UE's. Largely ignored by the HSS +# IMSI: UE's IMSI value +# Key: UE's key, where other keys are derived from. Stored in hexadecimal +# OP: Operator's code, sotred in hexadecimal +# AMF: Authentication management feild, stored in hexadecimal +# +# Note: Lines starting by '#' are ignored +ue1,001010123456789,00112233445566778899aabbccddeeff,63BFA50EE6523365FF14C1F45F88737D,8000 +ue2,001010123456780,00112233445566778899aabbccddeeaa,63BFA50EE6523365FF14C1F45F88737D,2000 From 0865571ec22547a7a5726d8ae5c6a6ccb555bacc Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 14 Dec 2017 08:38:37 +0000 Subject: [PATCH 121/172] Minor commit (clearing whitespaces, etc.) --- srsepc/src/mme/s1ap.cc | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 370d7318a..a995da889 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -107,10 +107,10 @@ s1ap::stop() void s1ap::delete_enb_ctx(int32_t assoc_id) -{ +{ std::map::iterator it_assoc = m_sctp_to_enb_id.find(assoc_id); uint16_t enb_id = it_assoc->second; - + std::map::iterator it_ctx = m_active_enbs.find(enb_id); if(it_ctx == m_active_enbs.end() || it_assoc == m_sctp_to_enb_id.end()) { @@ -120,10 +120,10 @@ s1ap::delete_enb_ctx(int32_t assoc_id) m_s1ap_log->info("Deleting eNB context. eNB Id: 0x%x\n", enb_id); m_s1ap_log->console("Deleting eNB context. eNB Id: 0x%x\n", enb_id); - + //Delete connected UEs ctx delete_ues_in_enb(enb_id); - + //Delete eNB delete it_ctx->second; m_active_enbs.erase(it_ctx); @@ -149,7 +149,6 @@ s1ap::delete_ues_in_enb(uint16_t enb_id) } - int s1ap::get_s1_mme() { @@ -292,8 +291,8 @@ s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, st //Log S1 Setup Request Info m_s1ap_log->console("Received S1 Setup Request. Association: %d\n",enb_sri->sinfo_assoc_id); print_enb_ctx_info(enb_ctx); - - //Check matching PLMNs + + //Check matching PLMNs if(enb_ctx.plmn!=m_plmn){ m_s1ap_log->console("Sending S1 Setup Failure - Unkown PLMN\n"); m_s1ap_log->info("Sending S1 Setup Failure - Unkown PLMN\n"); @@ -316,12 +315,12 @@ s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, st m_sctp_to_enb_id.insert(std::pair(enb_sri->sinfo_assoc_id, enb_ptr->enb_id)); m_enb_id_to_ue_ids.insert(std::pair >(enb_ptr->enb_id,ue_set)); } - + m_s1ap_mngmt_proc.pack_s1_setup_response(m_s1ap_args, &reply_msg); m_s1ap_log->console("Sending S1 Setup Response\n"); m_s1ap_log->info("Sending S1 Setup Response\n"); } - + //Send Reply to eNB ssize_t n_sent = sctp_send(m_s1mme,reply_msg.msg, reply_msg.N_bytes, enb_sri, 0); if(n_sent == -1) @@ -329,9 +328,7 @@ s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, st m_s1ap_log->console("Failed to send S1 Setup Setup Reply"); return false; } - return true; - } bool From 9a0b883296d7ecdef394c548d2e310e4db174e69 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 15 Dec 2017 18:20:57 +0000 Subject: [PATCH 122/172] Added XOR support the the HSS. --- srsepc/epc.conf.example | 3 +- srsepc/hdr/hss/hss.h | 12 ++- srsepc/src/hss/hss.cc | 154 ++++++++++++++++++++++++++- srsepc/src/main.cc | 5 +- srsepc/src/mme/s1ap.cc | 4 +- srsepc/src/mme/s1ap_nas_transport.cc | 60 +++++------ srsepc/user_db.csv | 2 +- 7 files changed, 200 insertions(+), 40 deletions(-) diff --git a/srsepc/epc.conf.example b/srsepc/epc.conf.example index 544e153d1..34df1eb74 100644 --- a/srsepc/epc.conf.example +++ b/srsepc/epc.conf.example @@ -14,7 +14,7 @@ # ##################################################################### [mme] -mme_code = 0x19 +mme_code = 0x1a mme_group = 0x0001 tac = 0x0001 mcc = 001 @@ -28,6 +28,7 @@ mme_bind_addr = 127.0.0.0/24 # ##################################################################### [hss] +auth_algo = xor db_file = user_db.csv diff --git a/srsepc/hdr/hss/hss.h b/srsepc/hdr/hss/hss.h index 06ca26842..5278c99bc 100644 --- a/srsepc/hdr/hss/hss.h +++ b/srsepc/hdr/hss/hss.h @@ -39,10 +39,12 @@ #include "srslte/common/log_filter.h" #include "srslte/common/buffer_pool.h" #include +#include namespace srsepc{ typedef struct{ + std::string auth_algo; std::string db_file; }hss_args_t; @@ -54,7 +56,10 @@ typedef struct{ uint8_t amf[2]; }hss_ue_ctx_t; - +enum hss_auth_algo { + HSS_ALGO_XOR, + HSS_ALGO_MILENAGE +}; class hss { @@ -62,12 +67,15 @@ public: static hss* get_instance(void); static void cleanup(void); int init(hss_args_t *hss_args, srslte::log_filter* hss_log); + bool set_auth_algo(std::string auth_algo); bool read_db_file(std::string db_file); void get_sqn(uint8_t sqn[6]); void gen_rand(uint8_t rand_[16]); bool get_k_amf_op(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op); + bool gen_auth_info_answer(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres); bool gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres); + bool gen_auth_info_answer_xor(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres); std::vector split_string(const std::string &str, char delimiter); void get_uint_vec_from_hex_str(const std::string &key_str, uint8_t *key, uint len); @@ -84,6 +92,8 @@ private: std::map m_imsi_to_ue_ctx; + enum hss_auth_algo m_auth_algo; + /*Logs*/ srslte::log_filter *m_hss_log; diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index 32bc1d54d..e8cbf52ae 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -39,7 +39,8 @@ hss* hss::m_instance = NULL; boost::mutex hss_instance_mutex; hss::hss() - :m_sqn(0x112233445566) +// :m_sqn(0x112233445566) + :m_sqn(0) { m_pool = srslte::byte_buffer_pool::get_instance(); return; @@ -80,14 +81,42 @@ hss::init(hss_args_t *hss_args, srslte::log_filter *hss_log) srand(time(NULL)); /*Init loggers*/ m_hss_log = hss_log; - m_hss_log->info("HSS Initialized\n"); - m_hss_log->console("HSS Initialized\n"); + /*Set authentication algorithm*/ + if(set_auth_algo(hss_args->auth_algo) == false) + { + return -1; + } /*Read user information from DB*/ - read_db_file(hss_args->db_file); + if(read_db_file(hss_args->db_file) == false) + { + return -1; + } + + m_hss_log->info("HSS Initialized. DB file %s, authentication algorithm %s\n", hss_args->db_file.c_str(),hss_args->auth_algo.c_str()); + m_hss_log->console("HSS Initialized\n"); return 0; } +bool +hss::set_auth_algo(std::string auth_algo) +{ + if(auth_algo != "xor" && auth_algo != "milenage" ) + { + m_hss_log->error("Unrecognized authentication algorithm. auth_algo = %s\n", auth_algo.c_str()); + return false; + } + if(auth_algo == "xor") + { + m_auth_algo = HSS_ALGO_XOR; + } + else + { + m_auth_algo = HSS_ALGO_MILENAGE; + } + return true; +} + bool hss::read_db_file(std::string db_filename) { @@ -128,6 +157,23 @@ hss::read_db_file(std::string db_filename) return true; } +bool +hss::gen_auth_info_answer(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres) +{ + bool ret = false; + switch (m_auth_algo) + { + case HSS_ALGO_XOR: + ret = gen_auth_info_answer_xor(imsi, k_asme, autn, rand, xres); + break; + case HSS_ALGO_MILENAGE: + ret = gen_auth_info_answer_milenage(imsi, k_asme, autn, rand, xres); + break; + } + return ret; + +} + bool hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres) { @@ -196,6 +242,106 @@ hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn return true; } +bool +hss::gen_auth_info_answer_xor(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres) +{ + uint8_t k[16]; + uint8_t amf[2]; + uint8_t op[16]; + uint8_t sqn[6]; + + uint8_t xdout[16]; + uint8_t cdout[8]; + + uint8_t ck[16]; + uint8_t ik[16]; + uint8_t ak[6]; + uint8_t mac[8]; + + uint16_t mcc=61441; //001 + uint16_t mnc=65281; //01 + + int i = 0; + + if(!get_k_amf_op(imsi,k,amf,op)) + { + return false; + } + gen_rand(rand); + get_sqn(sqn); + + // Use RAND and K to compute RES, CK, IK and AK + for(i=0; i<16; i++) { + xdout[i] = k[i]^rand[i]; + } + + for(i=0; i<16; i++) { + xres[i] = xdout[i]; + ck[i] = xdout[(i+1)%16]; + ik[i] = xdout[(i+2)%16]; + } + for(i=0; i<6; i++) { + ak[i] = xdout[i+3]; + } + + // Generate cdout + for(i=0; i<6; i++) { + cdout[i] = sqn[i]; + } + for(i=0; i<2; i++) { + cdout[6+i] = amf[i]; + } + + // Generate MAC + for(i=0;i<8;i++) { + mac[i] = xdout[i] ^ cdout[i]; + } + + //Generate AUTN (autn = sqn ^ ak |+| amf |+| mac) + for(int i=0;i<6;i++ ) + { + autn[i] = sqn[i]^ak[i]; + } + for(int i=0;i<2;i++) + { + autn[6+i]=amf[i]; + } + for(int i=0;i<8;i++) + { + autn[8+i]=mac[i]; + } + + // Generate K_asme + security_generate_k_asme( ck, + ik, + ak, + sqn, + mcc, + mnc, + k_asme); + + //Generate AUTN (autn = sqn ^ ak |+| amf |+| mac) + for(int i=0;i<6;i++ ) + { + autn[i] = sqn[i]^ak[i]; + } + for(int i=0;i<2;i++) + { + autn[6+i]=amf[i]; + } + for(int i=0;i<8;i++) + { + autn[8+i]=mac[i]; + } + + m_hss_log->debug_hex(sqn, 6, "User SQN : "); + m_hss_log->debug_hex(autn, 8, "User AUTN: "); + m_hss_log->debug_hex(xres, 8, "User XRES: "); + + return true; +} + + bool hss::get_k_amf_op(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op ) { diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index 5db3235fa..b579464cb 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -74,6 +74,7 @@ parse_args(all_args_t *args, int argc, char* argv[]) { string spgw_bind_addr; string sgi_if_addr; string hss_db_file; + string hss_auth_algo; // Command line only options bpo::options_description general("General options"); @@ -94,6 +95,7 @@ parse_args(all_args_t *args, int argc, char* argv[]) { ("mme.mnc", bpo::value(&mnc)->default_value("01"), "Mobile Network Code") ("mme.mme_bind_addr", bpo::value(&mme_bind_addr)->default_value("127.0.0.1"),"IP address of MME for S1 connnection") ("hss.db_file", bpo::value(&hss_db_file)->default_value("ue_db.csv"),".csv file that stores UE's keys") + ("hss.auth_algo", bpo::value(&hss_auth_algo)->default_value("milenage"),"HSS uthentication algorithm.") ("spgw.gtpu_bind_addr", bpo::value(&spgw_bind_addr)->default_value("127.0.0.1"),"IP address of SP-GW for the S1-U connection") ("spgw.sgi_if_addr", bpo::value(&sgi_if_addr)->default_value("176.16.0.1"),"IP address of TUN interface for the SGi connection") ; @@ -166,11 +168,12 @@ parse_args(all_args_t *args, int argc, char* argv[]) { if(!srslte::string_to_mnc(mnc, &args->mme_args.s1ap_args.mnc)) { cout << "Error parsing enb.mnc:" << mnc << " - must be a 2 or 3-digit string." << endl; } - + args->mme_args.s1ap_args.mme_bind_addr = mme_bind_addr; args->spgw_args.gtpu_bind_addr = spgw_bind_addr; args->spgw_args.sgi_if_addr = sgi_if_addr; args->hss_args.db_file = hss_db_file; + args->hss_args.auth_algo = hss_auth_algo; return; } diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index a995da889..0b3bc3e8d 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -378,7 +378,7 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini memcpy(&ue_ctx.enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); //Get Authentication Vectors from HSS - if(!m_hss->gen_auth_info_answer_milenage(imsi, ue_ctx.security_ctxt.k_asme, autn, rand, ue_ctx.security_ctxt.xres)) + if(!m_hss->gen_auth_info_answer(imsi, ue_ctx.security_ctxt.k_asme, autn, rand, ue_ctx.security_ctxt.xres)) { m_s1ap_log->console("User not found. IMSI %015lu\n",imsi); m_s1ap_log->info("User not found. IMSI %015lu\n",imsi); @@ -468,7 +468,7 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT return true; //no need for reply. FIXME this should be better structured... break; default: - m_s1ap_log->info("Unhandled NAS message"); + m_s1ap_log->info("Unhandled NAS message 0x%x\n", msg_type ); return false; //FIXME (nas_msg deallocate needs to be called) } diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 490fc46c4..75265691e 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -82,7 +82,7 @@ s1ap_nas_transport::unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA return false; } - if(pdn_con_req->pdn_type != LIBLTE_MME_PDN_TYPE_IPV4) + if(pdn_con_req->pdn_type == LIBLTE_MME_PDN_TYPE_IPV6) { m_s1ap_log->error("PDN Connectivity Request: Only IPv4 connectivity supported.\n"); return false; @@ -331,59 +331,59 @@ s1ap_nas_transport::log_unhandled_attach_request_ies(const LIBLTE_MME_ATTACH_REQ { if(attach_req->old_p_tmsi_signature_present) { - m_s1ap_log->warning("NAS attach request: Old P-TMSI signature present, but not handled."); + m_s1ap_log->warning("NAS attach request: Old P-TMSI signature present, but not handled.\n"); } if(attach_req->additional_guti_present) { - m_s1ap_log->warning("NAS attach request: Aditional GUTI present, but not handled."); + m_s1ap_log->warning("NAS attach request: Aditional GUTI present, but not handled.\n"); } if(attach_req->last_visited_registered_tai_present) { - m_s1ap_log->warning("NAS attach request: Last visited registered TAI present, but not handled."); + m_s1ap_log->warning("NAS attach request: Last visited registered TAI present, but not handled.\n"); } if(attach_req->drx_param_present) { - m_s1ap_log->warning("NAS attach request: DRX Param present, but not handled."); + m_s1ap_log->warning("NAS attach request: DRX Param present, but not handled.\n"); } if(attach_req->ms_network_cap_present) { - m_s1ap_log->warning("NAS attach request: MS network cap present, but not handled."); + m_s1ap_log->warning("NAS attach request: MS network cap present, but not handled.\n"); } if(attach_req->old_lai_present) { - m_s1ap_log->warning("NAS attach request: Old LAI present, but not handled."); + m_s1ap_log->warning("NAS attach request: Old LAI present, but not handled.\n"); } if(attach_req->tmsi_status_present) { - m_s1ap_log->warning("NAS attach request: TSMI status present, but not handled."); + m_s1ap_log->warning("NAS attach request: TSMI status present, but not handled.\n"); } if(attach_req->ms_cm2_present) { - m_s1ap_log->warning("NAS attach request: MS CM2 present, but not handled."); + m_s1ap_log->warning("NAS attach request: MS CM2 present, but not handled.\n"); } if(attach_req->ms_cm3_present) { - m_s1ap_log->warning("NAS attach request: MS CM3 present, but not handled."); + m_s1ap_log->warning("NAS attach request: MS CM3 present, but not handled.\n"); } if(attach_req->supported_codecs_present) { - m_s1ap_log->warning("NAS attach request: Supported CODECs present, but not handled."); + m_s1ap_log->warning("NAS attach request: Supported CODECs present, but not handled.\n"); } if(attach_req->additional_update_type_present) { - m_s1ap_log->warning("NAS attach request: Additional Update Type present, but not handled."); + m_s1ap_log->warning("NAS attach request: Additional Update Type present, but not handled.\n"); } if(attach_req->voice_domain_pref_and_ue_usage_setting_present) { - m_s1ap_log->warning("NAS attach request: Voice domain preference and UE usage setting present, but not handled."); + m_s1ap_log->warning("NAS attach request: Voice domain preference and UE usage setting present, but not handled.\n"); } if(attach_req->device_properties_present) { - m_s1ap_log->warning("NAS attach request: Device properties present, but not handled."); + m_s1ap_log->warning("NAS attach request: Device properties present, but not handled.\n"); } if(attach_req->old_guti_type_present) { - m_s1ap_log->warning("NAS attach request: Old GUTI type present, but not handled."); + m_s1ap_log->warning("NAS attach request: Old GUTI type present, but not handled.\n"); } return; } @@ -394,19 +394,19 @@ s1ap_nas_transport::log_unhandled_pdn_con_request_ies(const LIBLTE_MME_PDN_CONNE //Handle the optional flags if(pdn_con_req->esm_info_transfer_flag_present) { - m_s1ap_log->warning("PDN Connectivity request: ESM info transfer flag properties present, but not handled."); + m_s1ap_log->warning("PDN Connectivity request: ESM info transfer flag properties present, but not handled.\n"); } if(pdn_con_req->apn_present) { - m_s1ap_log->warning("PDN Connectivity request: APN present, but not handled."); + m_s1ap_log->warning("PDN Connectivity request: APN present, but not handled.\n"); } if(pdn_con_req->protocol_cnfg_opts_present) { - m_s1ap_log->warning("PDN Connectivity request: Protocol Cnfg options present, but not handled."); + m_s1ap_log->warning("PDN Connectivity request: Protocol Cnfg options present, but not handled.\n"); } if(pdn_con_req->device_properties_present) { - m_s1ap_log->warning("PDN Connectivity request: Device properties present, but not handled."); + m_s1ap_log->warning("PDN Connectivity request: Device properties present, but not handled.\n"); } } @@ -415,37 +415,37 @@ void s1ap_nas_transport::log_unhandled_initial_ue_message_ies(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue) { if(init_ue->S_TMSI_present){ - m_s1ap_log->warning("S-TMSI present, but not handled."); + m_s1ap_log->warning("S-TMSI present, but not handled.\n"); } if(init_ue->CSG_Id_present){ - m_s1ap_log->warning("S-TMSI present, but not handled."); + m_s1ap_log->warning("S-TMSI present, but not handled.\n"); } if(init_ue->GUMMEI_ID_present){ - m_s1ap_log->warning("GUMMEI ID present, but not handled."); + m_s1ap_log->warning("GUMMEI ID present, but not handled.\n"); } if(init_ue->CellAccessMode_present){ - m_s1ap_log->warning("Cell Access Mode present, but not handled."); + m_s1ap_log->warning("Cell Access Mode present, but not handled.\n"); } if(init_ue->GW_TransportLayerAddress_present){ - m_s1ap_log->warning("GW Transport Layer present, but not handled."); + m_s1ap_log->warning("GW Transport Layer present, but not handled.\n"); } if(init_ue->GW_TransportLayerAddress_present){ - m_s1ap_log->warning("GW Transport Layer present, but not handled."); + m_s1ap_log->warning("GW Transport Layer present, but not handled.\n"); } if(init_ue->RelayNode_Indicator_present){ - m_s1ap_log->warning("Relay Node Indicator present, but not handled."); + m_s1ap_log->warning("Relay Node Indicator present, but not handled.\n"); } if(init_ue->GUMMEIType_present){ - m_s1ap_log->warning("GUMMEI Type present, but not handled."); + m_s1ap_log->warning("GUMMEI Type present, but not handled.\n"); } if(init_ue->Tunnel_Information_for_BBF_present){ - m_s1ap_log->warning("Tunnel Information for BBF present, but not handled."); + m_s1ap_log->warning("Tunnel Information for BBF present, but not handled.\n"); } if(init_ue->SIPTO_L_GW_TransportLayerAddress_present){ - m_s1ap_log->warning("SIPTO GW Transport Layer Address present, but not handled."); + m_s1ap_log->warning("SIPTO GW Transport Layer Address present, but not handled.\n"); } if(init_ue->LHN_ID_present){ - m_s1ap_log->warning("LHN Id present, but not handled."); + m_s1ap_log->warning("LHN Id present, but not handled.\n"); } return; } diff --git a/srsepc/user_db.csv b/srsepc/user_db.csv index f306adaa3..89d0dedf1 100644 --- a/srsepc/user_db.csv +++ b/srsepc/user_db.csv @@ -9,5 +9,5 @@ # AMF: Authentication management feild, stored in hexadecimal # # Note: Lines starting by '#' are ignored -ue1,001010123456789,00112233445566778899aabbccddeeff,63BFA50EE6523365FF14C1F45F88737D,8000 +ue1,001010123456789,00112233445566778899aabbccddeeff,63BFA50EE6523365FF14C1F45F88737D,9001 ue2,001010123456780,00112233445566778899aabbccddeeaa,63BFA50EE6523365FF14C1F45F88737D,2000 From 9d88d2b78f93c86c36455b0c90d4cc4433720ee8 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Sat, 16 Dec 2017 14:25:20 +0000 Subject: [PATCH 123/172] Addind replayed UE security capabilities. --- srsepc/hdr/mme/s1ap_common.h | 2 ++ srsepc/src/mme/s1ap.cc | 7 ++++++- srsepc/src/mme/s1ap_nas_transport.cc | 26 ++++++++++++++++++++++---- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/srsepc/hdr/mme/s1ap_common.h b/srsepc/hdr/mme/s1ap_common.h index 759f2d316..d09eb0566 100644 --- a/srsepc/hdr/mme/s1ap_common.h +++ b/srsepc/hdr/mme/s1ap_common.h @@ -24,6 +24,7 @@ #include "srslte/common/security.h" #include "srslte/asn1/gtpc_ies.h" #include "srslte/asn1/liblte_s1ap.h" +#include "srslte/asn1/liblte_mme.h" #include namespace srsepc{ @@ -90,6 +91,7 @@ typedef struct{ struct sctp_sndrcvinfo enb_sri; eps_security_ctx_t security_ctxt; erab_ctx_t erabs_ctx[MAX_ERABS_PER_UE]; + LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT ue_network_cap; } ue_ctx_t; }//namespace #endif diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 0b3bc3e8d..462dc336e 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -368,12 +368,17 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini } m_s1ap_log->console("Attach request from IMSI: %015lu\n", imsi); m_s1ap_log->info("Attach request from IMSI: %015lu\n", imsi); - + + //Get UE security capabilities + memcpy(&ue_ctx.ue_network_cap, &attach_req.ue_network_cap, sizeof(LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT)); + //FIXME use this info uint8_t eps_bearer_id = pdn_con_req.eps_bearer_id; //TODO: Unused uint8_t proc_transaction_id = pdn_con_req.proc_transaction_id; //TODO: Transaction ID unused m_s1ap_log->console("EPS Bearer id: %d\n", eps_bearer_id); + + //Add eNB info to UE ctxt memcpy(&ue_ctx.enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 75265691e..513109083 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -266,11 +266,29 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, sm_cmd.selected_nas_sec_algs.type_of_eia = LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_128_EIA1; sm_cmd.nas_ksi.tsc_flag=LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; - sm_cmd.nas_ksi.nas_ksi=0; - - //FIXME UE security cap not used by srsUE. - //sm_cmd.ue_security_cap; + sm_cmd.nas_ksi.nas_ksi=6; //111 no key available + //Replay UE security cap + memcpy(sm_cmd.ue_security_cap.eea,ue_ctx->ue_network_cap.eea,8*sizeof(bool)); + memcpy(sm_cmd.ue_security_cap.eia,ue_ctx->ue_network_cap.eia,8*sizeof(bool)); + sm_cmd.ue_security_cap.uea_present = ue_ctx->ue_network_cap.uea_present; + memcpy(sm_cmd.ue_security_cap.uea,ue_ctx->ue_network_cap.uea,8*sizeof(bool)); + sm_cmd.ue_security_cap.uia_present = ue_ctx->ue_network_cap.uia_present; + memcpy(sm_cmd.ue_security_cap.uia,ue_ctx->ue_network_cap.uia,8*sizeof(bool)); + sm_cmd.ue_security_cap.gea_present = false; + //memcpy(sm_cmd.ue_security_cap.gea,ue_ctx->ue_network_cap.gea,8*sizeof(bool)); + /* + typedef struct{ + bool eea[8]; + bool eia[8]; + bool uea[8]; + bool uea_present; + bool uia[8]; + bool uia_present; + bool gea[8]; + bool gea_present; + }LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT; + */ sm_cmd.imeisv_req_present=false; sm_cmd.nonce_ue_present=false; sm_cmd.nonce_mme_present=false; From 0884d353780db1b8a8d42b5646f3a0ef81a2a76b Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Sat, 16 Dec 2017 15:32:40 +0000 Subject: [PATCH 124/172] added replayed GRPS security capabilities. Moto G4 sends security mode complete. --- srsepc/epc.conf.example | 4 ++-- srsepc/hdr/mme/s1ap_common.h | 2 ++ srsepc/src/mme/s1ap.cc | 10 ++++++---- srsepc/src/mme/s1ap_nas_transport.cc | 6 +++--- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/srsepc/epc.conf.example b/srsepc/epc.conf.example index 34df1eb74..fe8a48735 100644 --- a/srsepc/epc.conf.example +++ b/srsepc/epc.conf.example @@ -19,7 +19,7 @@ mme_group = 0x0001 tac = 0x0001 mcc = 001 mnc = 01 -mme_bind_addr = 127.0.0.0/24 +mme_bind_addr = 127.0.1.100 ##################################################################### # HSS configuration @@ -40,5 +40,5 @@ db_file = user_db.csv ##################################################################### [spgw] -gtpu_bind_addr=127.0.0.2 +gtpu_bind_addr=127.0.1.100 sgi_if_addr=172.0.0.1 diff --git a/srsepc/hdr/mme/s1ap_common.h b/srsepc/hdr/mme/s1ap_common.h index d09eb0566..8fefbcf60 100644 --- a/srsepc/hdr/mme/s1ap_common.h +++ b/srsepc/hdr/mme/s1ap_common.h @@ -92,6 +92,8 @@ typedef struct{ eps_security_ctx_t security_ctxt; erab_ctx_t erabs_ctx[MAX_ERABS_PER_UE]; LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT ue_network_cap; + bool ms_network_cap_present; + LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT ms_network_cap; } ue_ctx_t; }//namespace #endif diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 462dc336e..1ba077134 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -369,16 +369,18 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini m_s1ap_log->console("Attach request from IMSI: %015lu\n", imsi); m_s1ap_log->info("Attach request from IMSI: %015lu\n", imsi); - //Get UE security capabilities + //Get UE network capabilities memcpy(&ue_ctx.ue_network_cap, &attach_req.ue_network_cap, sizeof(LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT)); - + ue_ctx.ms_network_cap_present = attach_req.ms_network_cap_present; + if(attach_req.ms_network_cap_present) + { + memcpy(&ue_ctx.ms_network_cap, &attach_req.ms_network_cap, sizeof(LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT)); + } //FIXME use this info uint8_t eps_bearer_id = pdn_con_req.eps_bearer_id; //TODO: Unused uint8_t proc_transaction_id = pdn_con_req.proc_transaction_id; //TODO: Transaction ID unused m_s1ap_log->console("EPS Bearer id: %d\n", eps_bearer_id); - - //Add eNB info to UE ctxt memcpy(&ue_ctx.enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 513109083..6b7db1b72 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -266,7 +266,7 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, sm_cmd.selected_nas_sec_algs.type_of_eia = LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_128_EIA1; sm_cmd.nas_ksi.tsc_flag=LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; - sm_cmd.nas_ksi.nas_ksi=6; //111 no key available + sm_cmd.nas_ksi.nas_ksi=0; //Replay UE security cap memcpy(sm_cmd.ue_security_cap.eea,ue_ctx->ue_network_cap.eea,8*sizeof(bool)); @@ -275,8 +275,8 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, memcpy(sm_cmd.ue_security_cap.uea,ue_ctx->ue_network_cap.uea,8*sizeof(bool)); sm_cmd.ue_security_cap.uia_present = ue_ctx->ue_network_cap.uia_present; memcpy(sm_cmd.ue_security_cap.uia,ue_ctx->ue_network_cap.uia,8*sizeof(bool)); - sm_cmd.ue_security_cap.gea_present = false; - //memcpy(sm_cmd.ue_security_cap.gea,ue_ctx->ue_network_cap.gea,8*sizeof(bool)); + sm_cmd.ue_security_cap.gea_present = ue_ctx->ms_network_cap_present; + memcpy(sm_cmd.ue_security_cap.gea,ue_ctx->ms_network_cap.gea,8*sizeof(bool)); /* typedef struct{ bool eea[8]; From 39e34a7bf92335ad41533d9d83b9be7955b2c682 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Sat, 16 Dec 2017 20:08:33 +0000 Subject: [PATCH 125/172] Starting to send ESM information request msg when required. --- srsepc/hdr/mme/s1ap.h | 1 + srsepc/hdr/mme/s1ap_common.h | 1 + srsepc/src/mme/s1ap.cc | 92 ++++++++++++++++++++++++++-- srsepc/src/mme/s1ap_nas_transport.cc | 13 +--- 4 files changed, 90 insertions(+), 17 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index ee5e5e6d1..3190488d7 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -88,6 +88,7 @@ public: bool handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx); void activate_eps_bearer(uint32_t mme_s1ap_id, uint8_t ebi); + bool pack_esm_information_request(srslte::byte_buffer_t* reply_msg, srsepc::ue_ctx_t* ue_ctx); void print_enb_ctx_info(const enb_ctx_t &enb_ctx); diff --git a/srsepc/hdr/mme/s1ap_common.h b/srsepc/hdr/mme/s1ap_common.h index 8fefbcf60..2ca8a8b78 100644 --- a/srsepc/hdr/mme/s1ap_common.h +++ b/srsepc/hdr/mme/s1ap_common.h @@ -94,6 +94,7 @@ typedef struct{ LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT ue_network_cap; bool ms_network_cap_present; LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT ms_network_cap; + bool eit; } ue_ctx_t; }//namespace #endif diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 1ba077134..e729699f3 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -379,6 +379,9 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini //FIXME use this info uint8_t eps_bearer_id = pdn_con_req.eps_bearer_id; //TODO: Unused uint8_t proc_transaction_id = pdn_con_req.proc_transaction_id; //TODO: Transaction ID unused + + //Save whether ESM information transfer is necessary + ue_ctx.eit = pdn_con_req.esm_info_transfer_flag_present; m_s1ap_log->console("EPS Bearer id: %d\n", eps_bearer_id); //Add eNB info to UE ctxt @@ -565,15 +568,94 @@ s1ap::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, srslte:: m_s1ap_log->info("Received Security Mode Command Complete. IMSI: %lu\n", ue_ctx->imsi); m_s1ap_log->console("Received Security Mode Command Complete. IMSI: %lu\n", ue_ctx->imsi); - - //FIXME The packging of GTP-C messages is not ready. - //This means that GTP-U tunnels are created with function calls, as opposed to GTP-C. - m_mme_gtpc->send_create_session_request(ue_ctx->imsi, ue_ctx->mme_ue_s1ap_id); - + if(ue_ctx->eit == true) + { + pack_esm_information_request(reply_msg, ue_ctx); + m_s1ap_log->console("Sending ESM information request\n"); + } + else + { + //FIXME The packging of GTP-C messages is not ready. + //This means that GTP-U tunnels are created with function calls, as opposed to GTP-C. + m_mme_gtpc->send_create_session_request(ue_ctx->imsi, ue_ctx->mme_ue_s1ap_id); + } return true; } +bool +s1ap::pack_esm_information_request(srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx) +{ + srslte::byte_buffer_t *nas_buffer = m_pool->allocate(); + //Setup initiating message + LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu; + bzero(&tx_pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); + + tx_pdu.ext = false; + tx_pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE; + + LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *init = &tx_pdu.choice.initiatingMessage; + init->procedureCode = LIBLTE_S1AP_PROC_ID_DOWNLINKNASTRANSPORT; + init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DOWNLINKNASTRANSPORT; + + //Setup Dw NAS structure + LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT *dw_nas = &init->choice.DownlinkNASTransport; + dw_nas->ext=false; + dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = ue_ctx->mme_ue_s1ap_id;//FIXME Change name + dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ue_ctx->enb_ue_s1ap_id; + dw_nas->HandoverRestrictionList_present=false; + dw_nas->SubscriberProfileIDforRFP_present=false; + + LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT esm_info_req; + /*typedef struct{ + uint8 eps_bearer_id; + uint8 proc_transaction_id; + }LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT;*/ + uint8_t sec_hdr_type=3; + + ue_ctx->security_ctxt.dl_nas_count++; + + LIBLTE_ERROR_ENUM err = liblte_mme_pack_esm_information_request_msg(&esm_info_req, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + if(err != LIBLTE_SUCCESS) + { + m_s1ap_log->error("Error packing Athentication Reject\n"); + m_s1ap_log->console("Error packing Athentication Reject\n"); + return false; + } + + uint8_t mac[4]; + srslte::security_128_eia1 (&ue_ctx->security_ctxt.k_nas_int[16], + ue_ctx->security_ctxt.dl_nas_count, + 0, + SECURITY_DIRECTION_DOWNLINK, + &nas_buffer->msg[5], + nas_buffer->N_bytes - 5, + mac + ); + + memcpy(&nas_buffer->msg[1],mac,4); + //Copy NAS PDU to Downlink NAS Trasport message buffer + memcpy(dw_nas->NAS_PDU.buffer, nas_buffer->msg, nas_buffer->N_bytes); + dw_nas->NAS_PDU.n_octets = nas_buffer->N_bytes; + + //Pack Downlink NAS Transport Message + err = liblte_s1ap_pack_s1ap_pdu(&tx_pdu, (LIBLTE_BYTE_MSG_STRUCT *) reply_msg); + if(err != LIBLTE_SUCCESS) + { + m_s1ap_log->error("Error packing Dw NAS Transport: Athentication Reject\n"); + m_s1ap_log->console("Error packing Downlink NAS Transport: Athentication Reject\n"); + return false; + } + + m_pool->deallocate(nas_buffer); + ssize_t n_sent = sctp_send(m_s1mme,reply_msg->msg, reply_msg->N_bytes, &ue_ctx->enb_sri, 0); + if(n_sent == -1) + { + m_s1ap_log->error("Failed to send NAS Attach Request"); + return false; + } + return true; +} bool s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp, struct srslte::gtpc_f_teid_ie sgw_ctrl_fteid) diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 6b7db1b72..b70b9a61b 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -277,18 +277,7 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, memcpy(sm_cmd.ue_security_cap.uia,ue_ctx->ue_network_cap.uia,8*sizeof(bool)); sm_cmd.ue_security_cap.gea_present = ue_ctx->ms_network_cap_present; memcpy(sm_cmd.ue_security_cap.gea,ue_ctx->ms_network_cap.gea,8*sizeof(bool)); - /* - typedef struct{ - bool eea[8]; - bool eia[8]; - bool uea[8]; - bool uea_present; - bool uia[8]; - bool uia_present; - bool gea[8]; - bool gea_present; - }LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT; - */ + sm_cmd.imeisv_req_present=false; sm_cmd.nonce_ue_present=false; sm_cmd.nonce_mme_present=false; From a4e17078352bf3f7f0aa490adb747f7bb0e90baa Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Sun, 17 Dec 2017 16:05:52 +0000 Subject: [PATCH 126/172] Fixed bug in packing ESM information request. --- lib/include/srslte/asn1/liblte_mme.h | 6 ++ lib/src/asn1/liblte_mme.cc | 124 ++++++++++++++++++++++++++- srsepc/hdr/mme/s1ap.h | 1 + srsepc/hdr/mme/s1ap_common.h | 1 + srsepc/src/mme/s1ap.cc | 93 +++++++++++++++++--- srsepc/src/mme/s1ap_nas_transport.cc | 8 +- 6 files changed, 212 insertions(+), 21 deletions(-) diff --git a/lib/include/srslte/asn1/liblte_mme.h b/lib/include/srslte/asn1/liblte_mme.h index 15799f7ca..e730ec822 100644 --- a/lib/include/srslte/asn1/liblte_mme.h +++ b/lib/include/srslte/asn1/liblte_mme.h @@ -3752,6 +3752,10 @@ typedef struct{ uint8 proc_transaction_id; }LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT; // Functions +LIBLTE_ERROR_ENUM srslte_mme_pack_esm_information_request_msg(LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT *esm_info_req, + uint8 sec_hdr_type, + uint32 count, + LIBLTE_BYTE_MSG_STRUCT *msg); LIBLTE_ERROR_ENUM liblte_mme_pack_esm_information_request_msg(LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT *esm_info_req, LIBLTE_BYTE_MSG_STRUCT *msg); LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_information_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, @@ -3782,6 +3786,8 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_esm_information_response_msg(LIBLTE_MME_ESM_IN LIBLTE_BYTE_MSG_STRUCT *msg); LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_information_response_msg(LIBLTE_BYTE_MSG_STRUCT *msg, LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT *esm_info_resp); +LIBLTE_ERROR_ENUM srslte_mme_unpack_esm_information_response_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT *esm_info_resp); /********************************************************************* Message Name: ESM Status diff --git a/lib/src/asn1/liblte_mme.cc b/lib/src/asn1/liblte_mme.cc index 4447b001f..54c6eb5ba 100644 --- a/lib/src/asn1/liblte_mme.cc +++ b/lib/src/asn1/liblte_mme.cc @@ -7063,7 +7063,6 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_identity_request_msg(LIBLTE_BYTE_MSG_STRUCT return(err); } - /********************************************************************* Message Name: Identity Response @@ -7101,6 +7100,7 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_identity_response_msg(LIBLTE_MME_ID_RESPONSE_M return(err); } + LIBLTE_ERROR_ENUM liblte_mme_unpack_identity_response_msg(LIBLTE_BYTE_MSG_STRUCT *msg, LIBLTE_MME_ID_RESPONSE_MSG_STRUCT *id_resp) { @@ -9850,11 +9850,15 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_deactivate_eps_bearer_context_request_msg(LI Description: Sent by the network to the UE to request the UE to provide ESM information, i.e. protocol configuration - options or APN or both. + options or APN or both. This function is being added + to support encryption and integrety protection on + ESM information transfer. Document Reference: 24.301 v10.2.0 Section 8.3.13 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_mme_pack_esm_information_request_msg(LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT *esm_info_req, +LIBLTE_ERROR_ENUM srslte_mme_pack_esm_information_request_msg(LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT *esm_info_req, + uint8 sec_hdr_type, + uint32 count, LIBLTE_BYTE_MSG_STRUCT *msg) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; @@ -9863,6 +9867,20 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_esm_information_request_msg(LIBLTE_MME_ESM_INF if(esm_info_req != NULL && msg != NULL) { + + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } // Protocol Discriminator and EPS Bearer ID *msg_ptr = (esm_info_req->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); msg_ptr++; @@ -9883,6 +9901,50 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_esm_information_request_msg(LIBLTE_MME_ESM_INF return(err); } + + +/********************************************************************* + Message Name: ESM Information Request + + Description: Sent by the network to the UE to request the UE to + provide ESM information, i.e. protocol configuration + options or APN or both. + + Document Reference: 24.301 v10.2.0 Section 8.3.13 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_esm_information_request_msg(LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT *esm_info_req, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(esm_info_req != NULL && + msg != NULL) + { + + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (esm_info_req->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; + + // Procedure Transaction ID + *msg_ptr = esm_info_req->proc_transaction_id; + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_REQUEST; + msg_ptr++; + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + + + LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_information_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT *esm_info_req) { @@ -9963,6 +10025,62 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_esm_information_response_msg(LIBLTE_MME_ESM_IN return(err); } +LIBLTE_ERROR_ENUM srslte_mme_unpack_esm_information_response_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT *esm_info_resp) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + esm_info_resp != NULL) + { + + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + // EPS Bearer ID + esm_info_resp->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; + + // Procedure Transaction ID + esm_info_resp->proc_transaction_id = *msg_ptr; + msg_ptr++; + + // Skip Message Type + msg_ptr++; + + // Access Point Name + if(LIBLTE_MME_ACCESS_POINT_NAME_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_access_point_name_ie(&msg_ptr, &esm_info_resp->apn); + esm_info_resp->apn_present = true; + }else{ + esm_info_resp->apn_present = false; + } + + // Protocol Configuration Options + if(LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &esm_info_resp->protocol_cnfg_opts); + esm_info_resp->protocol_cnfg_opts_present = true; + }else{ + esm_info_resp->protocol_cnfg_opts_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_information_response_msg(LIBLTE_BYTE_MSG_STRUCT *msg, LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT *esm_info_resp) { diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 3190488d7..7654fe06a 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -89,6 +89,7 @@ public: void activate_eps_bearer(uint32_t mme_s1ap_id, uint8_t ebi); bool pack_esm_information_request(srslte::byte_buffer_t* reply_msg, srsepc::ue_ctx_t* ue_ctx); + bool handle_esm_information_response(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t* ue_ctx); void print_enb_ctx_info(const enb_ctx_t &enb_ctx); diff --git a/srsepc/hdr/mme/s1ap_common.h b/srsepc/hdr/mme/s1ap_common.h index 2ca8a8b78..6ad87981c 100644 --- a/srsepc/hdr/mme/s1ap_common.h +++ b/srsepc/hdr/mme/s1ap_common.h @@ -95,6 +95,7 @@ typedef struct{ bool ms_network_cap_present; LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT ms_network_cap; bool eit; + uint8_t procedure_transaction_id; } ue_ctx_t; }//namespace #endif diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index e729699f3..745797f50 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -378,7 +378,7 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini } //FIXME use this info uint8_t eps_bearer_id = pdn_con_req.eps_bearer_id; //TODO: Unused - uint8_t proc_transaction_id = pdn_con_req.proc_transaction_id; //TODO: Transaction ID unused + ue_ctx.procedure_transaction_id = pdn_con_req.proc_transaction_id; //Save whether ESM information transfer is necessary ue_ctx.eit = pdn_con_req.esm_info_transfer_flag_present; @@ -473,12 +473,17 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT return true; //no need for reply. FIXME this should be better structured... break; case LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE: - m_s1ap_log->info("UL NAS: Received Attach Complete\n"); - handle_nas_attach_complete(nas_msg, reply_msg, ue_ctx); - return true; //no need for reply. FIXME this should be better structured... + m_s1ap_log->info("UL NAS: Received Attach Complete\n"); + handle_nas_attach_complete(nas_msg, reply_msg, ue_ctx); + return true; //no need for reply. FIXME this should be better structured... break; + case LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_RESPONSE: + m_s1ap_log->info("UL NAS: Received ESM Information Response\n"); + handle_esm_information_response(nas_msg,reply_msg,ue_ctx); + return true; default: - m_s1ap_log->info("Unhandled NAS message 0x%x\n", msg_type ); + m_s1ap_log->warning("Unhandled NAS message 0x%x\n", msg_type ); + m_s1ap_log->console("Unhandled NAS message 0x%x\n", msg_type ); return false; //FIXME (nas_msg deallocate needs to be called) } @@ -611,15 +616,17 @@ s1ap::pack_esm_information_request(srslte::byte_buffer_t *reply_msg, ue_ctx_t *u uint8 eps_bearer_id; uint8 proc_transaction_id; }LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT;*/ - uint8_t sec_hdr_type=3; + esm_info_req.eps_bearer_id=0; + esm_info_req.proc_transaction_id = ue_ctx->procedure_transaction_id; + uint8_t sec_hdr_type=2; ue_ctx->security_ctxt.dl_nas_count++; - LIBLTE_ERROR_ENUM err = liblte_mme_pack_esm_information_request_msg(&esm_info_req, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + LIBLTE_ERROR_ENUM err = srslte_mme_pack_esm_information_request_msg(&esm_info_req, sec_hdr_type,ue_ctx->security_ctxt.dl_nas_count,(LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); if(err != LIBLTE_SUCCESS) { - m_s1ap_log->error("Error packing Athentication Reject\n"); - m_s1ap_log->console("Error packing Athentication Reject\n"); + m_s1ap_log->error("Error packing ESM information request\n"); + m_s1ap_log->console("Error packing ESM information request\n"); return false; } @@ -657,6 +664,47 @@ s1ap::pack_esm_information_request(srslte::byte_buffer_t *reply_msg, ue_ctx_t *u return true; } + +bool +s1ap::handle_esm_information_response(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t* ue_ctx) +{ + LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT esm_info_resp; + /* + typedef struct{ + LIBLTE_MME_ACCESS_POINT_NAME_STRUCT apn; + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + bool apn_present; + bool protocol_cnfg_opts_present; + }LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT;*/ + //Get NAS authentication response + LIBLTE_ERROR_ENUM err = srslte_mme_unpack_esm_information_response_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &esm_info_resp); + if(err != LIBLTE_SUCCESS){ + m_s1ap_log->error("Error unpacking NAS authentication response. Error: %s\n", liblte_error_text[err]); + return false; + } + m_s1ap_log->info("ESM Info: EPS bearer id %d\n",esm_info_resp.eps_bearer_id); + if(esm_info_resp.apn_present) + { + m_s1ap_log->info("ESM Info: APN %s\n",esm_info_resp.eps_bearer_id); + m_s1ap_log->console("ESM Info: APN %s\n",esm_info_resp.eps_bearer_id); + } + /* + m_pool->deallocate(nas_buffer); + ssize_t n_sent = sctp_send(m_s1mme,reply_msg->msg, reply_msg->N_bytes, &ue_ctx->enb_sri, 0); + if(n_sent == -1) + { + m_s1ap_log->error("Failed to send NAS Attach Request"); + return false; + } + */ + + //FIXME The packging of GTP-C messages is not ready. + //This means that GTP-U tunnels are created with function calls, as opposed to GTP-C. + m_mme_gtpc->send_create_session_request(ue_ctx->imsi, ue_ctx->mme_ue_s1ap_id); + return true; +} bool s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp, struct srslte::gtpc_f_teid_ie sgw_ctrl_fteid) { @@ -692,8 +740,8 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: in_ctxt_req->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ue_ctx->enb_ue_s1ap_id; //Set UE-AMBR - in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL.BitRate=4294967295;//2^32-1 - in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL.BitRate=4294967295;//FIXME Get UE-AMBR from HSS + in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL.BitRate=1000000000;//2^32-1 + in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL.BitRate=1000000000;//FIXME Get UE-AMBR from HSS //Setup eRAB context in_ctxt_req->E_RABToBeSetupListCtxtSUReq.len = 1; @@ -721,9 +769,26 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: memcpy(erab_ctxt->gTP_TEID.buffer, &tmp_teid, sizeof(uint32_t)); //Set UE security capabilities and k_enb - in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer[0] = 0; //EEA0 - in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[0] = 1; //EIA1 - + for(int i = 0; i<16; i++) + { + if(ue_ctx->ue_network_cap.eea[i] == true) + { + in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer[i] = 1; //EEA supported + } + else + { + in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer[i] = 0; //EEA not supported + } + if(ue_ctx->ue_network_cap.eia[i] == true) + { + in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[i] = 1; //EEA supported + } + else + { + in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[i] = 0; //EEA not supported + } + // in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[0] = 1; //EIA1 + } uint8_t key_enb[32]; liblte_security_generate_k_enb(ue_ctx->security_ctxt.k_asme, ue_ctx->security_ctxt.dl_nas_count, key_enb); liblte_unpack(key_enb, 32, in_ctxt_req->SecurityKey.buffer); diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index b70b9a61b..9dd1666d1 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -476,7 +476,7 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE attach_accept.tai_list.N_tais = 1; attach_accept.tai_list.tai[0].mcc = 1; attach_accept.tai_list.tai[0].mnc = 1; - attach_accept.tai_list.tai[0].tac = 1; + attach_accept.tai_list.tai[0].tac = 7; //Make sure all unused options are set to false attach_accept.guti_present=false; @@ -507,10 +507,10 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE act_def_eps_bearer_context_req.eps_qos.mbr_dl_ext = 250; //FIXME check //set apn //act_def_eps_bearer_context_req.apn - std::string apn("internet"); + std::string apn("test123"); act_def_eps_bearer_context_req.apn.apn = apn; //FIXME - act_def_eps_bearer_context_req.proc_transaction_id = 1; //FIXME + act_def_eps_bearer_context_req.proc_transaction_id = ue_ctx->procedure_transaction_id; //FIXME //Make sure unused options are set to false @@ -536,7 +536,7 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE bool br_ext_present; }LIBLTE_MME_EPS_QUALITY_OF_SERVICE_STRUCT; */ - uint8_t sec_hdr_type =3; + uint8_t sec_hdr_type =2; ue_ctx->security_ctxt.dl_nas_count++; liblte_mme_pack_activate_default_eps_bearer_context_request_msg(&act_def_eps_bearer_context_req, &attach_accept.esm_msg); liblte_mme_pack_attach_accept_msg(&attach_accept, sec_hdr_type, ue_ctx->security_ctxt.dl_nas_count, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); From a8f268c55b76242659b0d6f6e34e2a944fe7fbb8 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Sun, 17 Dec 2017 16:30:50 +0000 Subject: [PATCH 127/172] Added cleanup functionality to the hss. --- srsepc/hdr/hss/hss.h | 2 ++ srsepc/src/hss/hss.cc | 23 +++++++++++++++++++---- srsepc/src/main.cc | 2 ++ 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/srsepc/hdr/hss/hss.h b/srsepc/hdr/hss/hss.h index 5278c99bc..4074aeb9a 100644 --- a/srsepc/hdr/hss/hss.h +++ b/srsepc/hdr/hss/hss.h @@ -67,6 +67,8 @@ public: static hss* get_instance(void); static void cleanup(void); int init(hss_args_t *hss_args, srslte::log_filter* hss_log); + void stop(void); + bool set_auth_algo(std::string auth_algo); bool read_db_file(std::string db_file); diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index e8cbf52ae..659933c7b 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -48,10 +48,6 @@ hss::hss() hss::~hss() { - if(m_db_file.is_open()) - { - m_db_file.close(); - } return; } @@ -98,6 +94,25 @@ hss::init(hss_args_t *hss_args, srslte::log_filter *hss_log) return 0; } +void +hss::stop(void) +{ + std::map::iterator it = m_imsi_to_ue_ctx.begin(); + while(it!=m_imsi_to_ue_ctx.end()) + { + m_hss_log->info("Deleting UE context in HSS. IMSI: %lu\n", it->second->imsi); + m_hss_log->console("Deleting UE context in HSS. IMSI: %lu\n", it->second->imsi); + delete it->second; + m_imsi_to_ue_ctx.erase(it++); + } + if(m_db_file.is_open()) + { + m_db_file.close(); + } + return; +} + + bool hss::set_auth_algo(std::string auth_algo) { diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index b579464cb..7b6ec7025 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -250,6 +250,8 @@ main (int argc,char * argv[] ) mme->cleanup(); spgw->stop(); spgw->cleanup(); + hss->stop(); + hss->cleanup(); cout << std::endl <<"--- exiting ---" << endl; return 0; From 80780bfb2f27ca89e39274d5a6a4421af320aca1 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Sun, 17 Dec 2017 17:54:26 +0000 Subject: [PATCH 128/172] Changed the way UE's IPs are assigned --- srsepc/epc.conf.example | 2 +- srsepc/hdr/spgw/spgw.h | 4 ++++ srsepc/src/spgw/spgw.cc | 17 ++++++++++++++++- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/srsepc/epc.conf.example b/srsepc/epc.conf.example index fe8a48735..7dd211a0c 100644 --- a/srsepc/epc.conf.example +++ b/srsepc/epc.conf.example @@ -41,4 +41,4 @@ db_file = user_db.csv [spgw] gtpu_bind_addr=127.0.1.100 -sgi_if_addr=172.0.0.1 +sgi_if_addr=172.16.0.1 diff --git a/srsepc/hdr/spgw/spgw.h b/srsepc/hdr/spgw/spgw.h index 00d2ebd12..047a5db9a 100644 --- a/srsepc/hdr/spgw/spgw.h +++ b/srsepc/hdr/spgw/spgw.h @@ -87,6 +87,8 @@ private: srslte::error_t init_sgi_if(spgw_args_t *args); srslte::error_t init_s1u(spgw_args_t *args); + srslte::error_t init_ue_ip(spgw_args_t *args); + uint64_t get_new_ctrl_teid(); uint64_t get_new_user_teid(); in_addr_t get_new_ue_ipv4(); @@ -112,6 +114,8 @@ private: std::map m_teid_to_tunnel_ctx; //Map control TEID to tunnel ctx. Usefull to get reply ctrl TEID, UE IP, etc. std::map m_ip_to_teid; //Map IP to User-plane TEID for downlink traffic + uint32_t m_h_next_ue_ip; + /*Logs*/ srslte::log_filter *m_spgw_log; diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index a69ff04d5..afd7efef4 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -104,6 +104,13 @@ spgw::init(spgw_args_t* args, srslte::log_filter *spgw_log) m_spgw_log->console("Could not initialize the S1-U interface.\n"); return -1; } + //Initialize UE ip pool + err = init_ue_ip(args); + if (err != srslte::ERROR_NONE) + { + m_spgw_log->console("Could not initialize the S1-U interface.\n"); + return -1; + } //Init mutex pthread_mutex_init(&m_mutex,NULL); @@ -237,6 +244,13 @@ spgw::init_s1u(spgw_args_t *args) return srslte::ERROR_NONE; } +srslte::error_t +spgw::init_ue_ip(spgw_args_t *args) +{ + m_h_next_ue_ip = ntohl(inet_addr(args->sgi_if_addr.c_str())); + return srslte::ERROR_NONE; +} + void spgw::run_thread() { @@ -395,7 +409,8 @@ spgw::get_new_user_teid() in_addr_t spgw::get_new_ue_ipv4() { - return inet_addr("172.0.0.2");//FIXME Tmp hack + m_h_next_ue_ip++; + return ntohl(m_h_next_ue_ip);//FIXME Tmp hack } void From cb5e329c22eb25e46cf861617bb1bc6eeb59242a Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Sun, 17 Dec 2017 19:55:12 +0000 Subject: [PATCH 129/172] Starting to release GTP-U tunnels when UE disconnects. --- srsepc/src/mme/s1ap.cc | 3 +++ srsepc/src/spgw/spgw.cc | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 745797f50..1bee40692 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -968,6 +968,9 @@ s1ap::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQU } ue_set->second.erase(mme_ue_s1ap_id); + //Delete any context at the SPGW + m_spgw->delete_session_request(ue_ctx->imsi); + //Delete UE context delete ue_ctx->second; m_active_ues.erase(ue_ctx); diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index afd7efef4..015ca8683 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -471,6 +471,12 @@ spgw::handle_create_session_request(struct srslte::gtpc_create_session_request * return; } +void +spgw::delete_session_request(uint64_t imsi) +{ + +} + void spgw::handle_modify_bearer_request(struct srslte::gtpc_pdu *mb_req_pdu, struct srslte::gtpc_pdu *mb_resp_pdu) { From e839d09b52d2daf7ccbb20acf20e2527d74dc824 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 18 Dec 2017 14:05:21 +0000 Subject: [PATCH 130/172] Fixed bug in generating keNB. --- srsepc/hdr/mme/s1ap_common.h | 2 +- srsepc/src/mme/s1ap.cc | 24 ++++++++++++++++++------ srsepc/src/spgw/spgw.cc | 3 ++- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/srsepc/hdr/mme/s1ap_common.h b/srsepc/hdr/mme/s1ap_common.h index 6ad87981c..f5462ad65 100644 --- a/srsepc/hdr/mme/s1ap_common.h +++ b/srsepc/hdr/mme/s1ap_common.h @@ -67,7 +67,7 @@ typedef struct{ typedef struct{ uint8_t k_asme[32]; - uint8_t xres[8]; + uint8_t xres[16]; //minimum 6, maximum 16 uint32_t dl_nas_count; uint32_t ul_nas_count; srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo; diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 1bee40692..6e26bf97e 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -384,6 +384,9 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini ue_ctx.eit = pdn_con_req.esm_info_transfer_flag_present; m_s1ap_log->console("EPS Bearer id: %d\n", eps_bearer_id); + //Initialize NAS count + ue_ctx.security_ctxt.ul_nas_count = 0; + ue_ctx.security_ctxt.dl_nas_count = 0; //Add eNB info to UE ctxt memcpy(&ue_ctx.enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); @@ -404,8 +407,10 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini ue_ctx.erabs_ctx[i].erab_id = i; } + printf("UL NAS count %d\n", ue_ctx.security_ctxt.ul_nas_count); ue_ctx_t *ue_ptr = new ue_ctx_t; memcpy(ue_ptr,&ue_ctx,sizeof(ue_ctx)); + printf("UL NAS count %d\n",(int) ue_ptr->security_ctxt.ul_nas_count); m_active_ues.insert(std::pair(ue_ptr->mme_ue_s1ap_id,ue_ptr)); std::map::iterator it_enb = m_sctp_to_enb_id.find(enb_sri->sinfo_assoc_id); @@ -454,6 +459,7 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT } m_s1ap_log->debug("Found UE. MME-UE S1AP id: %lu\n",mme_ue_s1ap_id); + printf("UL NAS count %d\n", ue_ctx->security_ctxt.ul_nas_count); //Get NAS message type uint8_t pd, msg_type; srslte::byte_buffer_t *nas_msg = m_pool->allocate(); @@ -470,16 +476,19 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT case LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMPLETE: m_s1ap_log->info("UL NAS: Received Security Mode Complete\n"); handle_nas_security_mode_complete(nas_msg, reply_msg, ue_ctx); + //ue_ctx->security_ctxt.ul_nas_count++; return true; //no need for reply. FIXME this should be better structured... break; case LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE: m_s1ap_log->info("UL NAS: Received Attach Complete\n"); handle_nas_attach_complete(nas_msg, reply_msg, ue_ctx); + ue_ctx->security_ctxt.ul_nas_count++; return true; //no need for reply. FIXME this should be better structured... break; case LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_RESPONSE: m_s1ap_log->info("UL NAS: Received ESM Information Response\n"); handle_esm_information_response(nas_msg,reply_msg,ue_ctx); + ue_ctx->security_ctxt.ul_nas_count++; return true; default: m_s1ap_log->warning("Unhandled NAS message 0x%x\n", msg_type ); @@ -769,9 +778,11 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: memcpy(erab_ctxt->gTP_TEID.buffer, &tmp_teid, sizeof(uint32_t)); //Set UE security capabilities and k_enb - for(int i = 0; i<16; i++) + bzero(in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer,sizeof(uint8_t)*16); + bzero(in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer,sizeof(uint8_t)*16); + for(int i = 0; i<3; i++) { - if(ue_ctx->ue_network_cap.eea[i] == true) + if(ue_ctx->ue_network_cap.eea[i+1] == true) { in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer[i] = 1; //EEA supported } @@ -779,7 +790,7 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: { in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer[i] = 0; //EEA not supported } - if(ue_ctx->ue_network_cap.eia[i] == true) + if(ue_ctx->ue_network_cap.eia[i+1] == true) { in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[i] = 1; //EEA supported } @@ -790,9 +801,9 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: // in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[0] = 1; //EIA1 } uint8_t key_enb[32]; - liblte_security_generate_k_enb(ue_ctx->security_ctxt.k_asme, ue_ctx->security_ctxt.dl_nas_count, key_enb); + liblte_security_generate_k_enb(ue_ctx->security_ctxt.k_asme, ue_ctx->security_ctxt.ul_nas_count, key_enb); liblte_unpack(key_enb, 32, in_ctxt_req->SecurityKey.buffer); - + m_s1ap_log->info("Generating KeNB with UL NAS COUNT: %d\n",ue_ctx->security_ctxt.ul_nas_count); //Set Attach accepted and activat default bearer NAS messages if(cs_resp->paa_present != true) { @@ -806,6 +817,7 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: } srslte::byte_buffer_t *nas_buffer = m_pool->allocate(); m_s1ap_nas_transport.pack_attach_accept(ue_ctx, erab_ctxt, &cs_resp->paa, nas_buffer); + LIBLTE_ERROR_ENUM err = liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)reply_buffer); if(err != LIBLTE_SUCCESS) @@ -969,7 +981,7 @@ s1ap::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQU ue_set->second.erase(mme_ue_s1ap_id); //Delete any context at the SPGW - m_spgw->delete_session_request(ue_ctx->imsi); + //m_spgw->delete_session_request(ue_ctx->imsi); //Delete UE context delete ue_ctx->second; diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index 015ca8683..1be10b171 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -471,12 +471,13 @@ spgw::handle_create_session_request(struct srslte::gtpc_create_session_request * return; } + /* void spgw::delete_session_request(uint64_t imsi) { } - + */ void spgw::handle_modify_bearer_request(struct srslte::gtpc_pdu *mb_req_pdu, struct srslte::gtpc_pdu *mb_resp_pdu) { From bc80cc3fffb8ec9defd8eb39668729456b8d8fea Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 18 Dec 2017 18:09:42 +0000 Subject: [PATCH 131/172] Starting to add DNS server configuration. --- srsepc/epc.conf.example | 2 +- srsepc/src/mme/s1ap_nas_transport.cc | 65 +++++++++++++++------------- 2 files changed, 37 insertions(+), 30 deletions(-) diff --git a/srsepc/epc.conf.example b/srsepc/epc.conf.example index 7dd211a0c..861bab6a8 100644 --- a/srsepc/epc.conf.example +++ b/srsepc/epc.conf.example @@ -16,7 +16,7 @@ [mme] mme_code = 0x1a mme_group = 0x0001 -tac = 0x0001 +tac = 0x0007 mcc = 001 mnc = 01 mme_bind_addr = 127.0.1.100 diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 9dd1666d1..8c920ab70 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -467,19 +467,41 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE m_s1ap_log->info("Packing Attach Accept\n"); //Attach accept - attach_accept.eps_attach_result = LIBLTE_MME_EPS_ATTACH_RESULT_EPS_ONLY; + attach_accept.eps_attach_result = LIBLTE_MME_EPS_ATTACH_RESULT_COMBINED_EPS_IMSI_ATTACH; //Mandatory //FIXME: Set t3412 from config - attach_accept.t3412.unit = LIBLTE_MME_GPRS_TIMER_DEACTIVATED; // 111 -> Timer deactivated - attach_accept.t3412.unit = 0; // No periodic tracking update + attach_accept.t3412.unit = LIBLTE_MME_GPRS_TIMER_UNIT_1_MINUTE; // GPRS 1 minute unit + attach_accept.t3412.value = 30; // 30 minute periodic timer //FIXME: Set tai_list from config attach_accept.tai_list.N_tais = 1; attach_accept.tai_list.tai[0].mcc = 1; attach_accept.tai_list.tai[0].mnc = 1; attach_accept.tai_list.tai[0].tac = 7; + //Allocate a GUTI ot the UE + attach_accept.guti_present=true; + attach_accept.guti.type_of_id = 6; //110 -> GUTI + attach_accept.guti.guti.mcc = 1; + attach_accept.guti.guti.mnc = 1; + attach_accept.guti.guti.mme_group_id = 0x0001; + attach_accept.guti.guti.mme_code = 0x1a; + attach_accept.guti.guti.m_tmsi = 0x124ae; + /* + typedef struct{ + uint32 m_tmsi; + uint16 mcc; + uint16 mnc; + uint16 mme_group_id; + uint8 mme_code; + }LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT; + typedef struct{ + LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti; + uint8 type_of_id; + uint8 imsi[15]; + uint8 imei[15]; + }LIBLTE_MME_EPS_MOBILE_ID_STRUCT;*/ + //Make sure all unused options are set to false - attach_accept.guti_present=false; attach_accept.lai_present=false; attach_accept.ms_id_present=false; attach_accept.emm_cause_present=false; @@ -509,33 +531,18 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE //act_def_eps_bearer_context_req.apn std::string apn("test123"); act_def_eps_bearer_context_req.apn.apn = apn; //FIXME - act_def_eps_bearer_context_req.proc_transaction_id = ue_ctx->procedure_transaction_id; //FIXME - //Make sure unused options are set to false - - /* - typedef struct{ - LIBLTE_MME_EPS_QUALITY_OF_SERVICE_STRUCT eps_qos; //TODO - LIBLTE_MME_ACCESS_POINT_NAME_STRUCT apn; //TODO - LIBLTE_MME_PDN_ADDRESS_STRUCT pdn_addr; //DONE - uint8 eps_bearer_id; //DONE - uint8 proc_transaction_id; -}LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT; - typedef struct{ - uint8 qci; - uint8 mbr_ul; - uint8 mbr_dl; - uint8 gbr_ul; - uint8 gbr_dl; - uint8 mbr_ul_ext; - uint8 mbr_dl_ext; - uint8 gbr_ul_ext; - uint8 gbr_dl_ext; - bool br_present; - bool br_ext_present; - }LIBLTE_MME_EPS_QUALITY_OF_SERVICE_STRUCT; - */ + //Set DNS server + act_def_eps_bearer_context_req.protocol_cnfg_opts_present = true; + act_def_eps_bearer_context_req.protocol_cnfg_opts.N_opts = 1; + act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].id = 0x0d; + act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].len = 4; + act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].contents[0] = 8; + act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].contents[1] = 8; + act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].contents[2] = 8; + act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].contents[3] = 8; + uint8_t sec_hdr_type =2; ue_ctx->security_ctxt.dl_nas_count++; liblte_mme_pack_activate_default_eps_bearer_context_request_msg(&act_def_eps_bearer_context_req, &attach_accept.esm_msg); From 031997d629b5123fbf7412b2e4f62c47a256d93f Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 19 Dec 2017 12:57:31 +0000 Subject: [PATCH 132/172] Adding script to marquerade outgoing interface. --- srsepc/if_masq.sh | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100755 srsepc/if_masq.sh diff --git a/srsepc/if_masq.sh b/srsepc/if_masq.sh new file mode 100755 index 000000000..ee6c41392 --- /dev/null +++ b/srsepc/if_masq.sh @@ -0,0 +1,30 @@ +#/bin/bash + +################################################################### +# +# This file is part of srsLTE. +# +# srsLTE is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# srsLTE is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# A copy of the GNU Affero General Public License can be found in +# the LICENSE file in the top-level directory of this distribution +# and at http://www.gnu.org/licenses/. +# +################################################################### + +#Check for sudo rights +sudo -v || exit + +echo "Masquerading Interface" + +echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward 1>/dev/null +sudo iptables -t nat -A POSTROUTING -o wlp58s0 -j MASQUERADE + From 9f79b4167f336c809e480cfbc3b20bd747edade8 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 19 Dec 2017 15:08:54 +0000 Subject: [PATCH 133/172] Small changes --- srsepc/src/mme/s1ap_nas_transport.cc | 2 +- srsepc/src/spgw/spgw.cc | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 8c920ab70..19e1231f4 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -467,7 +467,7 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE m_s1ap_log->info("Packing Attach Accept\n"); //Attach accept - attach_accept.eps_attach_result = LIBLTE_MME_EPS_ATTACH_RESULT_COMBINED_EPS_IMSI_ATTACH; + attach_accept.eps_attach_result = LIBLTE_MME_EPS_ATTACH_RESULT_EPS_ONLY; //Mandatory //FIXME: Set t3412 from config attach_accept.t3412.unit = LIBLTE_MME_GPRS_TIMER_UNIT_1_MINUTE; // GPRS 1 minute unit diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index 1be10b171..b9774ffb9 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -326,8 +326,8 @@ spgw::handle_sgi_pdu(srslte::byte_buffer_t *msg) dest_addr.s_addr = dest_ip; - m_spgw_log->console("IP version: %d\n", version); - m_spgw_log->console("Received packet to IP: %s\n", inet_ntoa(dest_addr)); + //m_spgw_log->console("IP version: %d\n", version); + //m_spgw_log->console("Received packet to IP: %s\n", inet_ntoa(dest_addr)); pthread_mutex_lock(&m_mutex); gtp_fteid_it = m_ip_to_teid.find(dest_ip); @@ -340,7 +340,7 @@ spgw::handle_sgi_pdu(srslte::byte_buffer_t *msg) if(ip_found == false) { - m_spgw_log->console("IP Packet is not for any UE\n"); + //m_spgw_log->console("IP Packet is not for any UE\n"); return; } struct sockaddr_in enb_addr; @@ -370,7 +370,7 @@ spgw::handle_sgi_pdu(srslte::byte_buffer_t *msg) m_spgw_log->console("Error sending packet to eNB\n"); return; } - m_spgw_log->console("Sent packet to %s:%d. Bytes=%d\n",inet_ntoa(enb_addr.sin_addr), GTPU_RX_PORT,n); + //m_spgw_log->console("Sent packet to %s:%d. Bytes=%d\n",inet_ntoa(enb_addr.sin_addr), GTPU_RX_PORT,n); return; } From da7c105a298d37dfe53e49bdea91e5d8d11e0b41 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 19 Dec 2017 16:54:44 +0000 Subject: [PATCH 134/172] Starting to cleanup S1AP --- srsepc/hdr/mme/s1ap.h | 10 ++-- srsepc/hdr/mme/s1ap_mngmt_proc.h | 20 ++++++- srsepc/src/mme/s1ap.cc | 25 ++++++-- srsepc/src/mme/s1ap_mngmt_proc.cc | 94 +++++++++++++++++++++++++++++++ 4 files changed, 137 insertions(+), 12 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 7654fe06a..eaf05d0fa 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -53,8 +53,6 @@ const uint16_t S1MME_PORT = 36412; class s1ap { public: - s1ap(); - virtual ~s1ap(); static s1ap* get_instance(); static void cleanup(); @@ -93,15 +91,17 @@ public: void print_enb_ctx_info(const enb_ctx_t &enb_ctx); + srslte::log_filter *m_s1ap_log; + private: + s1ap(); + virtual ~s1ap(); static s1ap *m_instance; s1ap_args_t m_s1ap_args; uint32_t m_plmn; srslte::byte_buffer_pool *m_pool; - srslte::logger *m_logger; - srslte::log_filter *m_s1ap_log; hss *m_hss; int m_s1mme; @@ -111,7 +111,7 @@ private: std::map > m_enb_id_to_ue_ids; uint32_t m_next_mme_ue_s1ap_id; - s1ap_mngmt_proc m_s1ap_mngmt_proc; + s1ap_mngmt_proc* m_s1ap_mngmt_proc; s1ap_nas_transport m_s1ap_nas_transport; //FIXME the GTP-C should be moved to the MME class, the the packaging of GTP-C messages is done. diff --git a/srsepc/hdr/mme/s1ap_mngmt_proc.h b/srsepc/hdr/mme/s1ap_mngmt_proc.h index 53c74f9eb..ec38c66cc 100644 --- a/srsepc/hdr/mme/s1ap_mngmt_proc.h +++ b/srsepc/hdr/mme/s1ap_mngmt_proc.h @@ -29,18 +29,34 @@ #include "srslte/asn1/liblte_s1ap.h" #include "srslte/common/common.h" #include "mme/s1ap_common.h" +#include "srslte/common/log_filter.h" namespace srsepc{ +class s1ap; + class s1ap_mngmt_proc { public: - s1ap_mngmt_proc(); - virtual ~s1ap_mngmt_proc(); + static s1ap_mngmt_proc *m_instance; + + static s1ap_mngmt_proc* get_instance(void); + static void cleanup(void); + + void init(void); + + //Packing/unpacking helper functions bool unpack_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, enb_ctx_t* enb_ctx); bool pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_ENUM cause, srslte::byte_buffer_t* msg); bool pack_s1_setup_response(s1ap_args_t s1ap_args, srslte::byte_buffer_t* msg); + +private: + s1ap_mngmt_proc(); + virtual ~s1ap_mngmt_proc(); + + s1ap* m_parent; + srslte::log_filter *m_s1ap_log; }; } //namespace srsepc diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 6e26bf97e..f66271bad 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -66,7 +66,6 @@ s1ap::cleanup(void) } } - int s1ap::init(s1ap_args_t s1ap_args, srslte::log_filter *s1ap_log) { @@ -75,12 +74,22 @@ s1ap::init(s1ap_args_t s1ap_args, srslte::log_filter *s1ap_log) m_s1ap_args = s1ap_args; srslte::s1ap_mccmnc_to_plmn(s1ap_args.mcc, s1ap_args.mnc, &m_plmn); + //Init log m_s1ap_log = s1ap_log; - m_s1ap_nas_transport.set_log(s1ap_log); + //Init message handlers + m_s1ap_mngmt_proc = s1ap_mngmt_proc::get_instance(); //Managment procedures (TS ) + m_s1ap_mngmt_proc->init(); + m_s1ap_nas_transport = s1ap_nas_transport::get_instance(); //NAS Transport procedures + m_s1ap_nas_transport->init(); + + //Get pointer to the HSS m_hss = hss::get_instance(); + + //Get pointer to GTP-C class m_mme_gtpc = mme_gtpc::get_instance(); + //Initialize S1-MME m_s1mme = enb_listen(); m_s1ap_log->info("S1AP Initialized\n"); @@ -102,6 +111,10 @@ s1ap::stop() delete it->second; m_active_enbs.erase(it++); } + + //Cleanup message handlers + s1ap_mngmt_proc::cleanup(); + s1ap_nas_transport::cleanup(); return; } @@ -272,6 +285,8 @@ s1ap::handle_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *msg) } return true; } + + bool s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri) { @@ -282,7 +297,7 @@ s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, st LIBLTE_S1AP_S1AP_PDU_STRUCT reply_pdu; - if(!m_s1ap_mngmt_proc.unpack_s1_setup_request(msg, &enb_ctx)) + if(!m_s1ap_mngmt_proc->unpack_s1_setup_request(msg, &enb_ctx)) { m_s1ap_log->error("Malformed S1 Setup Request\n"); return false; @@ -296,7 +311,7 @@ s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, st if(enb_ctx.plmn!=m_plmn){ m_s1ap_log->console("Sending S1 Setup Failure - Unkown PLMN\n"); m_s1ap_log->info("Sending S1 Setup Failure - Unkown PLMN\n"); - m_s1ap_mngmt_proc.pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_UNKNOWN_PLMN,&reply_msg); + m_s1ap_mngmt_proc->pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_UNKNOWN_PLMN,&reply_msg); } else{ std::map::iterator it = m_active_enbs.find(enb_ctx.enb_id); @@ -316,7 +331,7 @@ s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, st m_enb_id_to_ue_ids.insert(std::pair >(enb_ptr->enb_id,ue_set)); } - m_s1ap_mngmt_proc.pack_s1_setup_response(m_s1ap_args, &reply_msg); + m_s1ap_mngmt_proc->pack_s1_setup_response(m_s1ap_args, &reply_msg); m_s1ap_log->console("Sending S1 Setup Response\n"); m_s1ap_log->info("Sending S1 Setup Response\n"); } diff --git a/srsepc/src/mme/s1ap_mngmt_proc.cc b/srsepc/src/mme/s1ap_mngmt_proc.cc index 3a4768bc1..2f1123dcd 100644 --- a/srsepc/src/mme/s1ap_mngmt_proc.cc +++ b/srsepc/src/mme/s1ap_mngmt_proc.cc @@ -31,6 +31,10 @@ namespace srsepc{ +s1ap_mngmt_proc* s1ap_mngmt_proc::m_instance = NULL; +boost::mutex s1ap_mngmt_proc_instance_mutex; + + s1ap_mngmt_proc::s1ap_mngmt_proc() { } @@ -39,6 +43,96 @@ s1ap_mngmt_proc::~s1ap_mngmt_proc() { } +s1ap_mngmt_proc* +s1ap_mngmt_proc::get_instance(void) +{ + boost::mutex::scoped_lock lock(s1ap_mngmt_proc_instance_mutex); + if(NULL == m_instance) { + m_instance = new s1ap_mngmt_proc(); + } + return(m_instance); +} + +void +s1ap_mngmt_proc::cleanup(void) +{ + boost::mutex::scoped_lock lock(s1ap_mngmt_proc_instance_mutex); + if(NULL != m_instance) { + delete m_instance; + m_instance = NULL; + } +} + +void +s1ap_mngmt_proc::init(void) +{ + m_parent = s1ap::get_instance(); + m_s1ap_log = m_parent->m_s1ap_log; +} + /* +bool +s1ap_mngmt_proc::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri) +{ + + std::string mnc_str, mcc_str; + enb_ctx_t enb_ctx; + srslte::byte_buffer_t reply_msg; + + LIBLTE_S1AP_S1AP_PDU_STRUCT reply_pdu; + + if(!m_s1ap_mngmt_proc.unpack_s1_setup_request(msg, &enb_ctx)) + { + m_s1ap_log->error("Malformed S1 Setup Request\n"); + return false; + } + + //Log S1 Setup Request Info + m_s1ap_log->console("Received S1 Setup Request. Association: %d\n",enb_sri->sinfo_assoc_id); + print_enb_ctx_info(enb_ctx); + + //Check matching PLMNs + if(enb_ctx.plmn!=m_plmn){ + m_s1ap_log->console("Sending S1 Setup Failure - Unkown PLMN\n"); + m_s1ap_log->info("Sending S1 Setup Failure - Unkown PLMN\n"); + m_s1ap_mngmt_proc.pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_UNKNOWN_PLMN,&reply_msg); + } + else{ + std::map::iterator it = m_active_enbs.find(enb_ctx.enb_id); + if(it != m_active_enbs.end()) + { + //eNB already registered + //TODO replace enb_ctx + } + else + { + //new eNB + std::set ue_set; + enb_ctx_t *enb_ptr = new enb_ctx_t; + memcpy(enb_ptr,&enb_ctx,sizeof(enb_ctx)); + m_active_enbs.insert(std::pair(enb_ptr->enb_id,enb_ptr)); + m_sctp_to_enb_id.insert(std::pair(enb_sri->sinfo_assoc_id, enb_ptr->enb_id)); + m_enb_id_to_ue_ids.insert(std::pair >(enb_ptr->enb_id,ue_set)); + } + + m_s1ap_mngmt_proc.pack_s1_setup_response(m_s1ap_args, &reply_msg); + m_s1ap_log->console("Sending S1 Setup Response\n"); + m_s1ap_log->info("Sending S1 Setup Response\n"); + } + + //Send Reply to eNB + ssize_t n_sent = sctp_send(m_s1mme,reply_msg.msg, reply_msg.N_bytes, enb_sri, 0); + if(n_sent == -1) + { + m_s1ap_log->console("Failed to send S1 Setup Setup Reply"); + return false; + } + return true; +} + */ + +/* + * Packing/Unpacking helper functions. + */ bool s1ap_mngmt_proc::unpack_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, enb_ctx_t* enb_ctx) { From a5633bf1434925968ec4efb55541a86f316f3f44 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 19 Dec 2017 18:12:12 +0000 Subject: [PATCH 135/172] Continuing to clean S1AP --- srsepc/hdr/mme/s1ap.h | 2 +- srsepc/hdr/mme/s1ap_nas_transport.h | 13 +++++++++-- srsepc/src/mme/s1ap.cc | 12 +++++----- srsepc/src/mme/s1ap_nas_transport.cc | 33 +++++++++++++++++++++++++++- 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index eaf05d0fa..2d0d14924 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -112,7 +112,7 @@ private: uint32_t m_next_mme_ue_s1ap_id; s1ap_mngmt_proc* m_s1ap_mngmt_proc; - s1ap_nas_transport m_s1ap_nas_transport; + s1ap_nas_transport* m_s1ap_nas_transport; //FIXME the GTP-C should be moved to the MME class, the the packaging of GTP-C messages is done. mme_gtpc *m_mme_gtpc; diff --git a/srsepc/hdr/mme/s1ap_nas_transport.h b/srsepc/hdr/mme/s1ap_nas_transport.h index feb11379f..32f47b3e6 100644 --- a/srsepc/hdr/mme/s1ap_nas_transport.h +++ b/srsepc/hdr/mme/s1ap_nas_transport.h @@ -36,8 +36,11 @@ namespace srsepc{ class s1ap_nas_transport { public: - s1ap_nas_transport(); - virtual ~s1ap_nas_transport(); + + static s1ap_nas_transport* m_instance; + static s1ap_nas_transport* get_instance(void); + static void cleanup(void); + void init(void); void set_log(srslte::log *s1ap_logger); bool unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req, LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req); @@ -54,8 +57,14 @@ public: private: + s1ap_nas_transport(); + virtual ~s1ap_nas_transport(); + srslte::log *m_s1ap_log; srslte::byte_buffer_pool *m_pool; + + s1ap* m_parent; + }; } //namespace srsepc diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index f66271bad..b4df6883d 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -366,10 +366,10 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini m_s1ap_log->info("Received Initial UE Message. eNB-UE S1AP Id: %d\n", ue_ctx.enb_ue_s1ap_id); /*Log unhandled Initial UE message IEs*/ - m_s1ap_nas_transport.log_unhandled_initial_ue_message_ies(init_ue); + m_s1ap_nas_transport->log_unhandled_initial_ue_message_ies(init_ue); /*Get NAS Attach Request and PDN connectivity request messages*/ - if(!m_s1ap_nas_transport.unpack_initial_ue_message(init_ue, &attach_req,&pdn_con_req)) + if(!m_s1ap_nas_transport->unpack_initial_ue_message(init_ue, &attach_req,&pdn_con_req)) { //Could not decode the attach request and the PDN connectivity request. m_s1ap_log->error("Could not unpack NAS Attach Request and PDN connectivity request.\n"); @@ -435,7 +435,7 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini //Pack NAS Authentication Request in Downlink NAS Transport msg srslte::byte_buffer_t *reply_msg = m_pool->allocate(); - m_s1ap_nas_transport.pack_authentication_request(reply_msg, ue_ctx.enb_ue_s1ap_id, ue_ctx.mme_ue_s1ap_id, autn, rand); + m_s1ap_nas_transport->pack_authentication_request(reply_msg, ue_ctx.enb_ue_s1ap_id, ue_ctx.mme_ue_s1ap_id, autn, rand); //Send Reply to eNB ssize_t n_sent = sctp_send(m_s1mme,reply_msg->msg, reply_msg->N_bytes, enb_sri, 0); @@ -561,7 +561,7 @@ s1ap::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, srslte: m_s1ap_log->console("UE Authentication Rejected. IMSI: %lu\n", ue_ctx->imsi); m_s1ap_log->warning("UE Authentication Rejected. IMSI: %lu\n", ue_ctx->imsi); //Send back Athentication Reject - m_s1ap_nas_transport.pack_authentication_reject(reply_msg, ue_ctx->enb_ue_s1ap_id, ue_ctx->mme_ue_s1ap_id); + m_s1ap_nas_transport->pack_authentication_reject(reply_msg, ue_ctx->enb_ue_s1ap_id, ue_ctx->mme_ue_s1ap_id); return false; } else @@ -569,7 +569,7 @@ s1ap::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, srslte: m_s1ap_log->console("UE Authentication Accepted. IMSI: %lu\n", ue_ctx->imsi); m_s1ap_log->info("UE Authentication Accepted. IMSI: %lu\n", ue_ctx->imsi); //Send Security Mode Command - m_s1ap_nas_transport.pack_security_mode_command(reply_msg, ue_ctx); + m_s1ap_nas_transport->pack_security_mode_command(reply_msg, ue_ctx); } return true; @@ -831,7 +831,7 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: return false; } srslte::byte_buffer_t *nas_buffer = m_pool->allocate(); - m_s1ap_nas_transport.pack_attach_accept(ue_ctx, erab_ctxt, &cs_resp->paa, nas_buffer); + m_s1ap_nas_transport->pack_attach_accept(ue_ctx, erab_ctxt, &cs_resp->paa, nas_buffer); LIBLTE_ERROR_ENUM err = liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)reply_buffer); diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 19e1231f4..25f690953 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -30,9 +30,11 @@ namespace srsepc{ +s1ap_nas_transport* s1ap_nas_transport::m_instance = NULL; +boost::mutex s1ap_nas_transport_instance_mutex; + s1ap_nas_transport::s1ap_nas_transport() { - m_pool = srslte::byte_buffer_pool::get_instance(); return; } @@ -41,6 +43,35 @@ s1ap_nas_transport::~s1ap_nas_transport() return; } +s1ap_nas_transport* +s1ap_nas_transport::get_instance(void) +{ + boost::mutex::scoped_lock lock(s1ap_nas_transport_instance_mutex); + if(NULL == m_instance) { + m_instance = new s1ap_nas_transport(); + } + return(m_instance); +} + +void +s1ap_nas_transport::cleanup(void) +{ + boost::mutex::scoped_lock lock(s1ap_nas_transport_instance_mutex); + if(NULL != m_instance) { + delete m_instance; + m_instance = NULL; + } +} + +void +s1ap_nas_transport::init(void) +{ + m_parent = s1ap::get_instance(); + m_s1ap_log = m_parent->m_s1ap_log; + m_pool = srslte::byte_buffer_pool::get_instance(); +} + + void s1ap_nas_transport::set_log(srslte::log *s1ap_log) { From 1fb304ddd3ec463971067b109ac3c9a2277fcbf1 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 20 Dec 2017 10:45:55 +0000 Subject: [PATCH 136/172] Continuing to clean up. Moved S1 setup request to s1ap_mngmnt_proc --- srsepc/hdr/mme/s1ap.h | 14 +++++-- srsepc/hdr/mme/s1ap_mngmt_proc.h | 8 +++- srsepc/src/mme/s1ap.cc | 67 +++++++++++++++++++++++++------ srsepc/src/mme/s1ap_mngmt_proc.cc | 55 ++++++++++--------------- 4 files changed, 93 insertions(+), 51 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 2d0d14924..b8f0ff730 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -89,8 +89,13 @@ public: bool pack_esm_information_request(srslte::byte_buffer_t* reply_msg, srsepc::ue_ctx_t* ue_ctx); bool handle_esm_information_response(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t* ue_ctx); - void print_enb_ctx_info(const enb_ctx_t &enb_ctx); + void print_enb_ctx_info(const std::string &prefix, const enb_ctx_t &enb_ctx); + uint32_t get_plmn(); + enb_ctx_t* find_enb_ctx(uint16_t enb_id); + void add_enb_ctx(const enb_ctx_t &enb_ctx, const struct sctp_sndrcvinfo* enb_sri); + + s1ap_args_t m_s1ap_args; srslte::log_filter *m_s1ap_log; private: @@ -99,7 +104,6 @@ private: static s1ap *m_instance; - s1ap_args_t m_s1ap_args; uint32_t m_plmn; srslte::byte_buffer_pool *m_pool; @@ -118,7 +122,11 @@ private: mme_gtpc *m_mme_gtpc; }; - +inline uint32_t +s1ap::get_plmn() +{ + return m_plmn; +} } //namespace srsepc diff --git a/srsepc/hdr/mme/s1ap_mngmt_proc.h b/srsepc/hdr/mme/s1ap_mngmt_proc.h index ec38c66cc..7f5771676 100644 --- a/srsepc/hdr/mme/s1ap_mngmt_proc.h +++ b/srsepc/hdr/mme/s1ap_mngmt_proc.h @@ -43,9 +43,10 @@ public: static s1ap_mngmt_proc* get_instance(void); static void cleanup(void); - void init(void); + bool handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, sctp_sndrcvinfo *enb_sri, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); + //Packing/unpacking helper functions bool unpack_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, enb_ctx_t* enb_ctx); bool pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_ENUM cause, srslte::byte_buffer_t* msg); @@ -55,8 +56,11 @@ private: s1ap_mngmt_proc(); virtual ~s1ap_mngmt_proc(); - s1ap* m_parent; + s1ap* m_s1ap; srslte::log_filter *m_s1ap_log; + + int m_s1mme; + s1ap_args_t m_s1ap_args; }; } //namespace srsepc diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index b4df6883d..a75c8ebd5 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -254,10 +254,13 @@ s1ap::handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb bool s1ap::handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri) { + bool reply_flag = false; + srslte::byte_buffer_t * reply_buffer = m_pool->allocate(); + switch(msg->choice_type) { case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_S1SETUPREQUEST: m_s1ap_log->info("Received S1 Setup Request.\n"); - return handle_s1_setup_request(&msg->choice.S1SetupRequest, enb_sri); + m_s1ap_mngmt_proc->handle_s1_setup_request(&msg->choice.S1SetupRequest, enb_sri, reply_buffer, &reply_flag); case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_INITIALUEMESSAGE: m_s1ap_log->info("Received Initial UE Message.\n"); return handle_initial_ue_message(&msg->choice.InitialUEMessage, enb_sri); @@ -270,6 +273,18 @@ s1ap::handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, stru default: m_s1ap_log->error("Unhandled intiating message: %s\n", liblte_s1ap_initiatingmessage_choice_text[msg->choice_type]); } + //Send Reply to eNB + if(reply_flag == true) + { + ssize_t n_sent = sctp_send(m_s1mme,reply_buffer->msg, reply_buffer->N_bytes, enb_sri, 0); + if(n_sent == -1) + { + m_s1ap_log->console("Failed to send S1 Setup Setup Reply"); + m_pool->deallocate(reply_buffer); + return false; + } + } + m_pool->deallocate(reply_buffer); return true; } @@ -286,7 +301,7 @@ s1ap::handle_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *msg) return true; } - + /* bool s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri) { @@ -345,7 +360,7 @@ s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, st } return true; } - + */ bool s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, struct sctp_sndrcvinfo *enb_sri) { @@ -1005,6 +1020,32 @@ s1ap::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQU return true; } + +enb_ctx_t* +s1ap::find_enb_ctx(uint16_t enb_id) +{ + std::map::iterator it = m_active_enbs.find(enb_id); + if(it == m_active_enbs.end()) + { + return NULL; + } + else + { + return it->second; + } +} + +void +s1ap::add_enb_ctx(const enb_ctx_t &enb_ctx, const struct sctp_sndrcvinfo *enb_sri) +{ + std::set ue_set; + enb_ctx_t *enb_ptr = new enb_ctx_t; + memcpy(enb_ptr,&enb_ctx,sizeof(enb_ctx_t)); + m_active_enbs.insert(std::pair(enb_ptr->enb_id,enb_ptr)); + m_sctp_to_enb_id.insert(std::pair(enb_sri->sinfo_assoc_id, enb_ptr->enb_id)); + m_enb_id_to_ue_ids.insert(std::pair >(enb_ptr->enb_id,ue_set)); +} + void s1ap::activate_eps_bearer(uint32_t mme_s1ap_id, uint8_t ebi) { @@ -1028,33 +1069,33 @@ s1ap::activate_eps_bearer(uint32_t mme_s1ap_id, uint8_t ebi) } void -s1ap::print_enb_ctx_info(const enb_ctx_t &enb_ctx) +s1ap::print_enb_ctx_info(const std::string &prefix, const enb_ctx_t &enb_ctx) { std::string mnc_str, mcc_str; if(enb_ctx.enb_name_present) { - m_s1ap_log->console("S1 Setup Request - eNB Name: %s, eNB id: 0x%x\n", enb_ctx.enb_name, enb_ctx.enb_id); - m_s1ap_log->info("S1 Setup Request - eNB Name: %s, eNB id: 0x%x\n", enb_ctx.enb_name, enb_ctx.enb_id); + m_s1ap_log->console("%s - eNB Name: %s, eNB id: 0x%x\n",prefix.c_str(), enb_ctx.enb_name, enb_ctx.enb_id); + m_s1ap_log->info("%s - eNB Name: %s, eNB id: 0x%x\n", prefix.c_str(), enb_ctx.enb_name, enb_ctx.enb_id); } else { - m_s1ap_log->console("S1 Setup Request - eNB Id 0x%x\n", enb_ctx.enb_id); - m_s1ap_log->info("S1 Setup request - eNB Id 0x%x\n", enb_ctx.enb_id); + m_s1ap_log->console("%s - eNB Id 0x%x\n",prefix.c_str(), enb_ctx.enb_id); + m_s1ap_log->info("%s - eNB Id 0x%x\n", prefix.c_str(), enb_ctx.enb_id); } srslte::mcc_to_string(enb_ctx.mcc, &mcc_str); srslte::mnc_to_string(enb_ctx.mnc, &mnc_str); - m_s1ap_log->info("S1 Setup Request - MCC:%s, MNC:%s, PLMN: %d\n", mcc_str.c_str(), mnc_str.c_str(), enb_ctx.plmn); - m_s1ap_log->console("S1 Setup Request - MCC:%s, MNC:%s, PLMN: %d\n", mcc_str.c_str(), mnc_str.c_str(), enb_ctx.plmn); + m_s1ap_log->info("%s - MCC:%s, MNC:%s, PLMN: %d\n", prefix.c_str(), mcc_str.c_str(), mnc_str.c_str(), enb_ctx.plmn); + m_s1ap_log->console("%s - MCC:%s, MNC:%s, PLMN: %d\n", prefix.c_str(), mcc_str.c_str(), mnc_str.c_str(), enb_ctx.plmn); for(int i=0;iinfo("S1 Setup Request - TAC %d, B-PLMN %d\n",enb_ctx.tac[i],enb_ctx.bplmns[i][j]); - m_s1ap_log->console("S1 Setup Request - TAC %d, B-PLMN %d\n",enb_ctx.tac[i],enb_ctx.bplmns[i][j]); + m_s1ap_log->info("%s - TAC %d, B-PLMN %d\n",prefix.c_str(), enb_ctx.tac[i],enb_ctx.bplmns[i][j]); + m_s1ap_log->console("%s - TAC %d, B-PLMN %d\n",prefix.c_str(), enb_ctx.tac[i],enb_ctx.bplmns[i][j]); } } - m_s1ap_log->console("S1 Setup Request - Paging DRX %d\n",enb_ctx.drx); + m_s1ap_log->console("%s - Paging DRX %d\n",prefix.c_str(),enb_ctx.drx); return; } diff --git a/srsepc/src/mme/s1ap_mngmt_proc.cc b/srsepc/src/mme/s1ap_mngmt_proc.cc index 2f1123dcd..296952d7b 100644 --- a/srsepc/src/mme/s1ap_mngmt_proc.cc +++ b/srsepc/src/mme/s1ap_mngmt_proc.cc @@ -66,39 +66,39 @@ s1ap_mngmt_proc::cleanup(void) void s1ap_mngmt_proc::init(void) { - m_parent = s1ap::get_instance(); - m_s1ap_log = m_parent->m_s1ap_log; + m_s1ap = s1ap::get_instance(); + m_s1ap_log = m_s1ap->m_s1ap_log; + m_s1mme = m_s1ap->get_s1_mme(); + m_s1ap_args = m_s1ap->m_s1ap_args; } - /* -bool -s1ap_mngmt_proc::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri) -{ - - std::string mnc_str, mcc_str; - enb_ctx_t enb_ctx; - srslte::byte_buffer_t reply_msg; +bool +s1ap_mngmt_proc::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri, srslte::byte_buffer_t *reply_buffer, bool *reply_flag) +{ + + enb_ctx_t enb_ctx; LIBLTE_S1AP_S1AP_PDU_STRUCT reply_pdu; - if(!m_s1ap_mngmt_proc.unpack_s1_setup_request(msg, &enb_ctx)) + if(!unpack_s1_setup_request(msg, &enb_ctx)) { m_s1ap_log->error("Malformed S1 Setup Request\n"); return false; } //Log S1 Setup Request Info - m_s1ap_log->console("Received S1 Setup Request. Association: %d\n",enb_sri->sinfo_assoc_id); - print_enb_ctx_info(enb_ctx); + m_s1ap_log->console("Received S1 Setup Request."); + m_s1ap->print_enb_ctx_info(std::string("S1 Setup Request"),enb_ctx); //Check matching PLMNs - if(enb_ctx.plmn!=m_plmn){ + if(enb_ctx.plmn!=m_s1ap->get_plmn()){ + m_s1ap_log->console("Sending S1 Setup Failure - Unkown PLMN\n"); - m_s1ap_log->info("Sending S1 Setup Failure - Unkown PLMN\n"); - m_s1ap_mngmt_proc.pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_UNKNOWN_PLMN,&reply_msg); + m_s1ap_log->warning("Sending S1 Setup Failure - Unkown PLMN\n"); + pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_UNKNOWN_PLMN,reply_buffer); } else{ - std::map::iterator it = m_active_enbs.find(enb_ctx.enb_id); - if(it != m_active_enbs.end()) + enb_ctx_t *enb_ptr = m_s1ap->find_enb_ctx(enb_ctx.enb_id); + if(enb_ptr == NULL) { //eNB already registered //TODO replace enb_ctx @@ -106,29 +106,18 @@ s1ap_mngmt_proc::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRU else { //new eNB - std::set ue_set; - enb_ctx_t *enb_ptr = new enb_ctx_t; - memcpy(enb_ptr,&enb_ctx,sizeof(enb_ctx)); - m_active_enbs.insert(std::pair(enb_ptr->enb_id,enb_ptr)); - m_sctp_to_enb_id.insert(std::pair(enb_sri->sinfo_assoc_id, enb_ptr->enb_id)); - m_enb_id_to_ue_ids.insert(std::pair >(enb_ptr->enb_id,ue_set)); + m_s1ap->add_enb_ctx(enb_ctx,enb_sri); } - m_s1ap_mngmt_proc.pack_s1_setup_response(m_s1ap_args, &reply_msg); + pack_s1_setup_response(m_s1ap_args, reply_buffer); m_s1ap_log->console("Sending S1 Setup Response\n"); m_s1ap_log->info("Sending S1 Setup Response\n"); } - //Send Reply to eNB - ssize_t n_sent = sctp_send(m_s1mme,reply_msg.msg, reply_msg.N_bytes, enb_sri, 0); - if(n_sent == -1) - { - m_s1ap_log->console("Failed to send S1 Setup Setup Reply"); - return false; - } + *reply_flag = true; return true; } - */ + /* * Packing/Unpacking helper functions. From 18f864d21d5dcc67d9e9e3fadff660e12c4c6c45 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 20 Dec 2017 11:58:54 +0000 Subject: [PATCH 137/172] Fixed small bug --- srsepc/src/mme/s1ap.cc | 7 +++++++ srsepc/src/mme/s1ap_mngmt_proc.cc | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index a75c8ebd5..ac65e1ede 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -261,6 +261,7 @@ s1ap::handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, stru case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_S1SETUPREQUEST: m_s1ap_log->info("Received S1 Setup Request.\n"); m_s1ap_mngmt_proc->handle_s1_setup_request(&msg->choice.S1SetupRequest, enb_sri, reply_buffer, &reply_flag); + break; case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_INITIALUEMESSAGE: m_s1ap_log->info("Received Initial UE Message.\n"); return handle_initial_ue_message(&msg->choice.InitialUEMessage, enb_sri); @@ -446,6 +447,11 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini std::map::iterator it_enb = m_sctp_to_enb_id.find(enb_sri->sinfo_assoc_id); uint16_t enb_id = it_enb->second; std::map >::iterator it_ue_id = m_enb_id_to_ue_ids.find(enb_id); + if(it_ue_id==m_enb_id_to_ue_ids.end()) + { + m_s1ap_log->error("Could not find eNB's UEs\n"); + return false; + } it_ue_id->second.insert(ue_ptr->mme_ue_s1ap_id); //Pack NAS Authentication Request in Downlink NAS Transport msg @@ -1038,6 +1044,7 @@ s1ap::find_enb_ctx(uint16_t enb_id) void s1ap::add_enb_ctx(const enb_ctx_t &enb_ctx, const struct sctp_sndrcvinfo *enb_sri) { + m_s1ap_log->info("Adding new eNB context. eNB ID %d\n", enb_ctx.enb_id); std::set ue_set; enb_ctx_t *enb_ptr = new enb_ctx_t; memcpy(enb_ptr,&enb_ctx,sizeof(enb_ctx_t)); diff --git a/srsepc/src/mme/s1ap_mngmt_proc.cc b/srsepc/src/mme/s1ap_mngmt_proc.cc index 296952d7b..2b55f1f52 100644 --- a/srsepc/src/mme/s1ap_mngmt_proc.cc +++ b/srsepc/src/mme/s1ap_mngmt_proc.cc @@ -98,7 +98,7 @@ s1ap_mngmt_proc::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRU } else{ enb_ctx_t *enb_ptr = m_s1ap->find_enb_ctx(enb_ctx.enb_id); - if(enb_ptr == NULL) + if(enb_ptr != NULL) { //eNB already registered //TODO replace enb_ctx From d3e1e7d85382a76ac50e480b11f5eea1b2aaf1b1 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 20 Dec 2017 15:28:10 +0000 Subject: [PATCH 138/172] Continuing to cleanup. Moved initial ue message to nas_transport --- srsepc/hdr/mme/s1ap.h | 4 +- srsepc/hdr/mme/s1ap_nas_transport.h | 8 ++- srsepc/src/mme/s1ap.cc | 94 +++++++++----------------- srsepc/src/mme/s1ap_mngmt_proc.cc | 4 +- srsepc/src/mme/s1ap_nas_transport.cc | 98 ++++++++++++++++++++++++++-- 5 files changed, 132 insertions(+), 76 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index b8f0ff730..a7f2c2eea 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -92,8 +92,10 @@ public: void print_enb_ctx_info(const std::string &prefix, const enb_ctx_t &enb_ctx); uint32_t get_plmn(); + uint32_t get_next_mme_ue_s1ap_id(); enb_ctx_t* find_enb_ctx(uint16_t enb_id); - void add_enb_ctx(const enb_ctx_t &enb_ctx, const struct sctp_sndrcvinfo* enb_sri); + void add_new_enb_ctx(const enb_ctx_t &enb_ctx, const struct sctp_sndrcvinfo* enb_sri); + void add_new_ue_ctx(const ue_ctx_t &ue_ctx); s1ap_args_t m_s1ap_args; srslte::log_filter *m_s1ap_log; diff --git a/srsepc/hdr/mme/s1ap_nas_transport.h b/srsepc/hdr/mme/s1ap_nas_transport.h index 32f47b3e6..9804f2f9b 100644 --- a/srsepc/hdr/mme/s1ap_nas_transport.h +++ b/srsepc/hdr/mme/s1ap_nas_transport.h @@ -30,6 +30,7 @@ #include "srslte/common/buffer_pool.h" #include "mme/s1ap_common.h" #include "srslte/asn1/gtpc.h" +#include "hss/hss.h" namespace srsepc{ @@ -42,7 +43,8 @@ public: static void cleanup(void); void init(void); - void set_log(srslte::log *s1ap_logger); + bool handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, struct sctp_sndrcvinfo *enb_sri, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); + bool unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req, LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req); bool pack_authentication_request(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t next_mme_ue_s1ap_id, uint8_t *autn,uint8_t *rand); bool pack_authentication_reject(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id); @@ -63,8 +65,8 @@ private: srslte::log *m_s1ap_log; srslte::byte_buffer_pool *m_pool; - s1ap* m_parent; - + s1ap* m_s1ap; + hss* m_hss; }; } //namespace srsepc diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index ac65e1ede..c2afac543 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -264,7 +264,8 @@ s1ap::handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, stru break; case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_INITIALUEMESSAGE: m_s1ap_log->info("Received Initial UE Message.\n"); - return handle_initial_ue_message(&msg->choice.InitialUEMessage, enb_sri); + m_s1ap_nas_transport->handle_initial_ue_message(&msg->choice.InitialUEMessage, enb_sri, reply_buffer, &reply_flag); + break; case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UPLINKNASTRANSPORT: m_s1ap_log->info("Received Uplink NAS Transport Message.\n"); return handle_uplink_nas_transport(&msg->choice.UplinkNASTransport, enb_sri); @@ -302,66 +303,6 @@ s1ap::handle_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *msg) return true; } - /* -bool -s1ap::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri) -{ - - std::string mnc_str, mcc_str; - enb_ctx_t enb_ctx; - srslte::byte_buffer_t reply_msg; - - LIBLTE_S1AP_S1AP_PDU_STRUCT reply_pdu; - - if(!m_s1ap_mngmt_proc->unpack_s1_setup_request(msg, &enb_ctx)) - { - m_s1ap_log->error("Malformed S1 Setup Request\n"); - return false; - } - - //Log S1 Setup Request Info - m_s1ap_log->console("Received S1 Setup Request. Association: %d\n",enb_sri->sinfo_assoc_id); - print_enb_ctx_info(enb_ctx); - - //Check matching PLMNs - if(enb_ctx.plmn!=m_plmn){ - m_s1ap_log->console("Sending S1 Setup Failure - Unkown PLMN\n"); - m_s1ap_log->info("Sending S1 Setup Failure - Unkown PLMN\n"); - m_s1ap_mngmt_proc->pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_UNKNOWN_PLMN,&reply_msg); - } - else{ - std::map::iterator it = m_active_enbs.find(enb_ctx.enb_id); - if(it != m_active_enbs.end()) - { - //eNB already registered - //TODO replace enb_ctx - } - else - { - //new eNB - std::set ue_set; - enb_ctx_t *enb_ptr = new enb_ctx_t; - memcpy(enb_ptr,&enb_ctx,sizeof(enb_ctx)); - m_active_enbs.insert(std::pair(enb_ptr->enb_id,enb_ptr)); - m_sctp_to_enb_id.insert(std::pair(enb_sri->sinfo_assoc_id, enb_ptr->enb_id)); - m_enb_id_to_ue_ids.insert(std::pair >(enb_ptr->enb_id,ue_set)); - } - - m_s1ap_mngmt_proc->pack_s1_setup_response(m_s1ap_args, &reply_msg); - m_s1ap_log->console("Sending S1 Setup Response\n"); - m_s1ap_log->info("Sending S1 Setup Response\n"); - } - - //Send Reply to eNB - ssize_t n_sent = sctp_send(m_s1mme,reply_msg.msg, reply_msg.N_bytes, enb_sri, 0); - if(n_sent == -1) - { - m_s1ap_log->console("Failed to send S1 Setup Setup Reply"); - return false; - } - return true; -} - */ bool s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, struct sctp_sndrcvinfo *enb_sri) { @@ -438,10 +379,8 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini ue_ctx.erabs_ctx[i].erab_id = i; } - printf("UL NAS count %d\n", ue_ctx.security_ctxt.ul_nas_count); ue_ctx_t *ue_ptr = new ue_ctx_t; memcpy(ue_ptr,&ue_ctx,sizeof(ue_ctx)); - printf("UL NAS count %d\n",(int) ue_ptr->security_ctxt.ul_nas_count); m_active_ues.insert(std::pair(ue_ptr->mme_ue_s1ap_id,ue_ptr)); std::map::iterator it_enb = m_sctp_to_enb_id.find(enb_sri->sinfo_assoc_id); @@ -1042,7 +981,7 @@ s1ap::find_enb_ctx(uint16_t enb_id) } void -s1ap::add_enb_ctx(const enb_ctx_t &enb_ctx, const struct sctp_sndrcvinfo *enb_sri) +s1ap::add_new_enb_ctx(const enb_ctx_t &enb_ctx, const struct sctp_sndrcvinfo *enb_sri) { m_s1ap_log->info("Adding new eNB context. eNB ID %d\n", enb_ctx.enb_id); std::set ue_set; @@ -1051,6 +990,33 @@ s1ap::add_enb_ctx(const enb_ctx_t &enb_ctx, const struct sctp_sndrcvinfo *enb_sr m_active_enbs.insert(std::pair(enb_ptr->enb_id,enb_ptr)); m_sctp_to_enb_id.insert(std::pair(enb_sri->sinfo_assoc_id, enb_ptr->enb_id)); m_enb_id_to_ue_ids.insert(std::pair >(enb_ptr->enb_id,ue_set)); + + return; +} + +void +s1ap::add_new_ue_ctx(const ue_ctx_t &ue_ctx) +{ + ue_ctx_t *ue_ptr = new ue_ctx_t; + memcpy(ue_ptr,&ue_ctx,sizeof(ue_ctx)); + m_active_ues.insert(std::pair(ue_ptr->mme_ue_s1ap_id,ue_ptr)); + + std::map::iterator it_enb = m_sctp_to_enb_id.find(ue_ptr->enb_sri.sinfo_assoc_id); + uint16_t enb_id = it_enb->second; + std::map >::iterator it_ue_id = m_enb_id_to_ue_ids.find(enb_id); + if(it_ue_id==m_enb_id_to_ue_ids.end()) + { + m_s1ap_log->error("Could not find eNB's UEs\n"); + return; + } + it_ue_id->second.insert(ue_ptr->mme_ue_s1ap_id); + return; +} + +uint32_t +s1ap::get_next_mme_ue_s1ap_id() +{ + return m_next_mme_ue_s1ap_id++; } void diff --git a/srsepc/src/mme/s1ap_mngmt_proc.cc b/srsepc/src/mme/s1ap_mngmt_proc.cc index 2b55f1f52..8fa469ec3 100644 --- a/srsepc/src/mme/s1ap_mngmt_proc.cc +++ b/srsepc/src/mme/s1ap_mngmt_proc.cc @@ -86,7 +86,7 @@ s1ap_mngmt_proc::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRU } //Log S1 Setup Request Info - m_s1ap_log->console("Received S1 Setup Request."); + m_s1ap_log->console("Received S1 Setup Request.\n"); m_s1ap->print_enb_ctx_info(std::string("S1 Setup Request"),enb_ctx); //Check matching PLMNs @@ -106,7 +106,7 @@ s1ap_mngmt_proc::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRU else { //new eNB - m_s1ap->add_enb_ctx(enb_ctx,enb_sri); + m_s1ap->add_new_enb_ctx(enb_ctx,enb_sri); } pack_s1_setup_response(m_s1ap_args, reply_buffer); diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 25f690953..56947b526 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -66,19 +66,105 @@ s1ap_nas_transport::cleanup(void) void s1ap_nas_transport::init(void) { - m_parent = s1ap::get_instance(); - m_s1ap_log = m_parent->m_s1ap_log; + m_s1ap = s1ap::get_instance(); + m_s1ap_log = m_s1ap->m_s1ap_log; m_pool = srslte::byte_buffer_pool::get_instance(); + + m_hss = hss::get_instance(); } -void -s1ap_nas_transport::set_log(srslte::log *s1ap_log) +bool +s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, struct sctp_sndrcvinfo *enb_sri, srslte::byte_buffer_t *reply_buffer, bool *reply_flag) { - m_s1ap_log=s1ap_log; - return; + LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT attach_req; + LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT pdn_con_req; + + uint64_t imsi; + uint8_t k_asme[32]; + uint8_t autn[16]; + uint8_t rand[6]; + uint8_t xres[8]; + + ue_ctx_t ue_ctx; + + m_s1ap_log->console("Received Initial UE Message.\n"); + m_s1ap_log->info("Received Initial UE Message.\n"); + + //Get info from initial UE message + ue_ctx.enb_ue_s1ap_id = init_ue->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; + + //Log unhandled Initial UE message IEs + log_unhandled_initial_ue_message_ies(init_ue); + + //Get NAS Attach Request and PDN connectivity request messages + if(!unpack_initial_ue_message(init_ue, &attach_req,&pdn_con_req)) + { + //Could not decode the attach request and the PDN connectivity request. + m_s1ap_log->error("Could not unpack NAS Attach Request and PDN connectivity request.\n"); + return false; + } + + //Get IMSI + imsi = 0; + for(int i=0;i<=14;i++){ + imsi += attach_req.eps_mobile_id.imsi[i]*std::pow(10,14-i); + } + m_s1ap_log->console("Attach request from IMSI: %015lu\n", imsi); + m_s1ap_log->info("Attach request from IMSI: %015lu\n", imsi); + + //Get UE network capabilities + memcpy(&ue_ctx.ue_network_cap, &attach_req.ue_network_cap, sizeof(LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT)); + ue_ctx.ms_network_cap_present = attach_req.ms_network_cap_present; + if(attach_req.ms_network_cap_present) + { + memcpy(&ue_ctx.ms_network_cap, &attach_req.ms_network_cap, sizeof(LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT)); + } + //FIXME use this info + uint8_t eps_bearer_id = pdn_con_req.eps_bearer_id; //TODO: Unused + ue_ctx.procedure_transaction_id = pdn_con_req.proc_transaction_id; + + //Save whether ESM information transfer is necessary + ue_ctx.eit = pdn_con_req.esm_info_transfer_flag_present; + m_s1ap_log->console("EPS Bearer id: %d\n", eps_bearer_id); + + //Initialize NAS count + ue_ctx.security_ctxt.ul_nas_count = 0; + ue_ctx.security_ctxt.dl_nas_count = 0; + //Add eNB info to UE ctxt + memcpy(&ue_ctx.enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); + + //Get Authentication Vectors from HSS + if(!m_hss->gen_auth_info_answer(imsi, ue_ctx.security_ctxt.k_asme, autn, rand, ue_ctx.security_ctxt.xres)) + { + m_s1ap_log->console("User not found. IMSI %015lu\n",imsi); + m_s1ap_log->info("User not found. IMSI %015lu\n",imsi); + return false; + } + + //Save UE context + ue_ctx.imsi = imsi; + ue_ctx.mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id(); + + for(uint i = 0 ; i< MAX_ERABS_PER_UE; i++) + { + ue_ctx.erabs_ctx[i].state = ERAB_DEACTIVATED; + ue_ctx.erabs_ctx[i].erab_id = i; + } + m_s1ap->add_new_ue_ctx(ue_ctx); + + //Pack NAS Authentication Request in Downlink NAS Transport msg + pack_authentication_request(reply_buffer, ue_ctx.enb_ue_s1ap_id, ue_ctx.mme_ue_s1ap_id, autn, rand); + + //Send reply to eNB + *reply_flag = true; + m_s1ap_log->info("DL NAS: Sent Athentication Request\n"); + //TODO Start T3460 Timer! + return true; } + +/*Packing/Unpacking helper functions*/ bool s1ap_nas_transport::unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req, From 1f55db09dcd5e34facf52474c80541a8eb4a5920 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 20 Dec 2017 15:33:56 +0000 Subject: [PATCH 139/172] Deleted unused functions --- srsepc/hdr/mme/s1ap.h | 4 -- srsepc/src/mme/s1ap.cc | 107 ----------------------------------------- 2 files changed, 111 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index a7f2c2eea..76d8aedfa 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -69,10 +69,6 @@ public: bool handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb_sri); bool handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri); - bool handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri); - bool send_s1_setup_failure(struct sctp_sndrcvinfo *enb_sri); - bool send_s1_setup_response(struct sctp_sndrcvinfo *enb_sri); - bool handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, struct sctp_sndrcvinfo *enb_sri); bool handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, struct sctp_sndrcvinfo *enb_sri); bool handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri); diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index c2afac543..964e966c8 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -303,113 +303,6 @@ s1ap::handle_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *msg) return true; } -bool -s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, struct sctp_sndrcvinfo *enb_sri) -{ - LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT attach_req; - LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT pdn_con_req; - - uint64_t imsi; - uint8_t k_asme[32]; - uint8_t autn[16]; - uint8_t rand[6]; - uint8_t xres[8]; - - ue_ctx_t ue_ctx; - - /*Get info from initial UE message*/ - ue_ctx.enb_ue_s1ap_id = init_ue->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; - m_s1ap_log->console("Received Initial UE Message. eNB-UE S1AP Id: %d\n", ue_ctx.enb_ue_s1ap_id); - m_s1ap_log->info("Received Initial UE Message. eNB-UE S1AP Id: %d\n", ue_ctx.enb_ue_s1ap_id); - - /*Log unhandled Initial UE message IEs*/ - m_s1ap_nas_transport->log_unhandled_initial_ue_message_ies(init_ue); - - /*Get NAS Attach Request and PDN connectivity request messages*/ - if(!m_s1ap_nas_transport->unpack_initial_ue_message(init_ue, &attach_req,&pdn_con_req)) - { - //Could not decode the attach request and the PDN connectivity request. - m_s1ap_log->error("Could not unpack NAS Attach Request and PDN connectivity request.\n"); - return false; - } - - //Get IMSI - imsi = 0; - for(int i=0;i<=14;i++){ - imsi += attach_req.eps_mobile_id.imsi[i]*std::pow(10,14-i); - } - m_s1ap_log->console("Attach request from IMSI: %015lu\n", imsi); - m_s1ap_log->info("Attach request from IMSI: %015lu\n", imsi); - - //Get UE network capabilities - memcpy(&ue_ctx.ue_network_cap, &attach_req.ue_network_cap, sizeof(LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT)); - ue_ctx.ms_network_cap_present = attach_req.ms_network_cap_present; - if(attach_req.ms_network_cap_present) - { - memcpy(&ue_ctx.ms_network_cap, &attach_req.ms_network_cap, sizeof(LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT)); - } - //FIXME use this info - uint8_t eps_bearer_id = pdn_con_req.eps_bearer_id; //TODO: Unused - ue_ctx.procedure_transaction_id = pdn_con_req.proc_transaction_id; - - //Save whether ESM information transfer is necessary - ue_ctx.eit = pdn_con_req.esm_info_transfer_flag_present; - m_s1ap_log->console("EPS Bearer id: %d\n", eps_bearer_id); - - //Initialize NAS count - ue_ctx.security_ctxt.ul_nas_count = 0; - ue_ctx.security_ctxt.dl_nas_count = 0; - //Add eNB info to UE ctxt - memcpy(&ue_ctx.enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); - - //Get Authentication Vectors from HSS - if(!m_hss->gen_auth_info_answer(imsi, ue_ctx.security_ctxt.k_asme, autn, rand, ue_ctx.security_ctxt.xres)) - { - m_s1ap_log->console("User not found. IMSI %015lu\n",imsi); - m_s1ap_log->info("User not found. IMSI %015lu\n",imsi); - return false; - } - - //Save UE context - ue_ctx.imsi = imsi; - ue_ctx.mme_ue_s1ap_id = m_next_mme_ue_s1ap_id++; - for(uint i = 0 ; i< MAX_ERABS_PER_UE; i++) - { - ue_ctx.erabs_ctx[i].state = ERAB_DEACTIVATED; - ue_ctx.erabs_ctx[i].erab_id = i; - } - - ue_ctx_t *ue_ptr = new ue_ctx_t; - memcpy(ue_ptr,&ue_ctx,sizeof(ue_ctx)); - m_active_ues.insert(std::pair(ue_ptr->mme_ue_s1ap_id,ue_ptr)); - - std::map::iterator it_enb = m_sctp_to_enb_id.find(enb_sri->sinfo_assoc_id); - uint16_t enb_id = it_enb->second; - std::map >::iterator it_ue_id = m_enb_id_to_ue_ids.find(enb_id); - if(it_ue_id==m_enb_id_to_ue_ids.end()) - { - m_s1ap_log->error("Could not find eNB's UEs\n"); - return false; - } - it_ue_id->second.insert(ue_ptr->mme_ue_s1ap_id); - - //Pack NAS Authentication Request in Downlink NAS Transport msg - srslte::byte_buffer_t *reply_msg = m_pool->allocate(); - m_s1ap_nas_transport->pack_authentication_request(reply_msg, ue_ctx.enb_ue_s1ap_id, ue_ctx.mme_ue_s1ap_id, autn, rand); - - //Send Reply to eNB - ssize_t n_sent = sctp_send(m_s1mme,reply_msg->msg, reply_msg->N_bytes, enb_sri, 0); - if(n_sent == -1) - { - m_s1ap_log->error("Failed to send NAS Attach Request"); - return false; - } - m_s1ap_log->info("DL NAS: Sent Athentication Request\n"); - m_pool->deallocate(reply_msg); - //TODO Start T3460 Timer! - return true; -} - bool s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, struct sctp_sndrcvinfo *enb_sri) { From c08b89f3e52a6db7131c4c8ba5dd613676e37a11 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 20 Dec 2017 18:16:54 +0000 Subject: [PATCH 140/172] Continuing cleaning up. Moved a lot of functionality to nas_transport --- srsepc/hdr/mme/s1ap.h | 1 + srsepc/hdr/mme/s1ap_nas_transport.h | 13 +- srsepc/src/mme/s1ap.cc | 350 ++------------------------- srsepc/src/mme/s1ap_nas_transport.cc | 282 +++++++++++++++++++++ 4 files changed, 311 insertions(+), 335 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 76d8aedfa..36c4d148e 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -91,6 +91,7 @@ public: uint32_t get_next_mme_ue_s1ap_id(); enb_ctx_t* find_enb_ctx(uint16_t enb_id); void add_new_enb_ctx(const enb_ctx_t &enb_ctx, const struct sctp_sndrcvinfo* enb_sri); + ue_ctx_t* find_ue_ctx(uint32_t mme_ue_s1ap_id); void add_new_ue_ctx(const ue_ctx_t &ue_ctx); s1ap_args_t m_s1ap_args; diff --git a/srsepc/hdr/mme/s1ap_nas_transport.h b/srsepc/hdr/mme/s1ap_nas_transport.h index 9804f2f9b..fd30d2630 100644 --- a/srsepc/hdr/mme/s1ap_nas_transport.h +++ b/srsepc/hdr/mme/s1ap_nas_transport.h @@ -31,6 +31,7 @@ #include "mme/s1ap_common.h" #include "srslte/asn1/gtpc.h" #include "hss/hss.h" +#include "mme/mme_gtpc.h" namespace srsepc{ @@ -44,13 +45,22 @@ public: void init(void); bool handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, struct sctp_sndrcvinfo *enb_sri, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); + bool handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, struct sctp_sndrcvinfo *enb_sri, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); + + bool handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_buffer, bool* reply_flag); + bool handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); + bool handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); + bool handle_esm_information_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag); bool unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req, LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req); + bool pack_authentication_request(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t next_mme_ue_s1ap_id, uint8_t *autn,uint8_t *rand); bool pack_authentication_reject(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id); - bool unpack_authentication_response(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT *auth_resp); + bool pack_security_mode_command(srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx); + bool pack_esm_information_request(srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx); + bool pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT *erab_ctxt, struct srslte::gtpc_pdn_address_allocation_ie *paa, srslte::byte_buffer_t *nas_buffer); void log_unhandled_attach_request_ies(const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req); @@ -67,6 +77,7 @@ private: s1ap* m_s1ap; hss* m_hss; + mme_gtpc* m_mme_gtpc; }; } //namespace srsepc diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 964e966c8..322ae165b 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -217,8 +217,6 @@ s1ap::enb_listen() } - - bool s1ap::handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb_sri) { @@ -268,7 +266,8 @@ s1ap::handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, stru break; case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UPLINKNASTRANSPORT: m_s1ap_log->info("Received Uplink NAS Transport Message.\n"); - return handle_uplink_nas_transport(&msg->choice.UplinkNASTransport, enb_sri); + m_s1ap_nas_transport->handle_uplink_nas_transport(&msg->choice.UplinkNASTransport, enb_sri, reply_buffer, &reply_flag); + break; case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UECONTEXTRELEASEREQUEST: m_s1ap_log->info("Received UE Context Release Request Message.\n"); return handle_ue_context_release_request(&msg->choice.UEContextReleaseRequest, enb_sri); @@ -303,285 +302,7 @@ s1ap::handle_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *msg) return true; } -bool -s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, struct sctp_sndrcvinfo *enb_sri) -{ - bool ue_valid = true; - uint32_t enb_ue_s1ap_id = ul_xport->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; - uint32_t mme_ue_s1ap_id = ul_xport->MME_UE_S1AP_ID.MME_UE_S1AP_ID; - ue_ctx_t *ue_ctx; - - srslte::byte_buffer_t *reply_msg = m_pool->allocate(); - - m_s1ap_log->console("Received Uplink NAS Transport message. MME-UE S1AP Id: %d\n",mme_ue_s1ap_id); - m_s1ap_log->info("Received Uplink NAS Transport message. MME-UE S1AP Id: %d\n",mme_ue_s1ap_id); - - std::map::iterator it = m_active_ues.find(mme_ue_s1ap_id); - ue_ctx = it->second; - if(it == m_active_ues.end()) - { - //TODO UE not registered, send error message. - m_s1ap_log->warning("Could not find UE. MME-UE S1AP id: %lu\n",mme_ue_s1ap_id); - return false; - } - m_s1ap_log->debug("Found UE. MME-UE S1AP id: %lu\n",mme_ue_s1ap_id); - - printf("UL NAS count %d\n", ue_ctx->security_ctxt.ul_nas_count); - //Get NAS message type - uint8_t pd, msg_type; - srslte::byte_buffer_t *nas_msg = m_pool->allocate(); - - memcpy(nas_msg->msg, &ul_xport->NAS_PDU.buffer, ul_xport->NAS_PDU.n_octets); - nas_msg->N_bytes = ul_xport->NAS_PDU.n_octets; - liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &pd, &msg_type); - - switch (msg_type) { - case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE: - handle_nas_authentication_response(nas_msg, reply_msg, ue_ctx); - m_s1ap_log->info("UL NAS: Received Authentication Response\n"); - break; - case LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMPLETE: - m_s1ap_log->info("UL NAS: Received Security Mode Complete\n"); - handle_nas_security_mode_complete(nas_msg, reply_msg, ue_ctx); - //ue_ctx->security_ctxt.ul_nas_count++; - return true; //no need for reply. FIXME this should be better structured... - break; - case LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE: - m_s1ap_log->info("UL NAS: Received Attach Complete\n"); - handle_nas_attach_complete(nas_msg, reply_msg, ue_ctx); - ue_ctx->security_ctxt.ul_nas_count++; - return true; //no need for reply. FIXME this should be better structured... - break; - case LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_RESPONSE: - m_s1ap_log->info("UL NAS: Received ESM Information Response\n"); - handle_esm_information_response(nas_msg,reply_msg,ue_ctx); - ue_ctx->security_ctxt.ul_nas_count++; - return true; - default: - m_s1ap_log->warning("Unhandled NAS message 0x%x\n", msg_type ); - m_s1ap_log->console("Unhandled NAS message 0x%x\n", msg_type ); - return false; //FIXME (nas_msg deallocate needs to be called) - } - - - //Send Reply to eNB - ssize_t n_sent = sctp_send(m_s1mme,reply_msg->msg, reply_msg->N_bytes, enb_sri, 0); - if(n_sent == -1) - { - m_s1ap_log->error("Failed to send NAS Attach Request"); - return false; - } - m_s1ap_log->info("DL NAS: Sent Downlink NAS message\n"); - m_s1ap_log->console("DL NAS: Sent Downlink NAs Message\n"); - m_pool->deallocate(nas_msg); - m_pool->deallocate(reply_msg); - - return true; -} - -bool -s1ap::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx) -{ - - LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT auth_resp; - bool ue_valid=true; - - //Get NAS authentication response - LIBLTE_ERROR_ENUM err = liblte_mme_unpack_authentication_response_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &auth_resp); - if(err != LIBLTE_SUCCESS){ - m_s1ap_log->error("Error unpacking NAS authentication response. Error: %s\n", liblte_error_text[err]); - return false; - } - - for(int i=0; i<8;i++) - { - if(auth_resp.res[i] != ue_ctx->security_ctxt.xres[i]) - { - ue_valid = false; - } - } - if(!ue_valid) - { - std::cout<security_ctxt.xres[i]; - } - std::cout<console("UE Authentication Rejected. IMSI: %lu\n", ue_ctx->imsi); - m_s1ap_log->warning("UE Authentication Rejected. IMSI: %lu\n", ue_ctx->imsi); - //Send back Athentication Reject - m_s1ap_nas_transport->pack_authentication_reject(reply_msg, ue_ctx->enb_ue_s1ap_id, ue_ctx->mme_ue_s1ap_id); - return false; - } - else - { - m_s1ap_log->console("UE Authentication Accepted. IMSI: %lu\n", ue_ctx->imsi); - m_s1ap_log->info("UE Authentication Accepted. IMSI: %lu\n", ue_ctx->imsi); - //Send Security Mode Command - m_s1ap_nas_transport->pack_security_mode_command(reply_msg, ue_ctx); - - } - return true; -} - -bool -s1ap::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx) -{ - LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT sm_comp; - - //Get NAS authentication response - LIBLTE_ERROR_ENUM err = liblte_mme_unpack_security_mode_complete_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &sm_comp); - if(err != LIBLTE_SUCCESS){ - m_s1ap_log->error("Error unpacking NAS authentication response. Error: %s\n", liblte_error_text[err]); - return false; - } - - //TODO Check integrity - - //TODO Handle imeisv - if(sm_comp.imeisv_present) - { - m_s1ap_log->warning("IMEI-SV present but not handled"); - } - - m_s1ap_log->info("Received Security Mode Command Complete. IMSI: %lu\n", ue_ctx->imsi); - m_s1ap_log->console("Received Security Mode Command Complete. IMSI: %lu\n", ue_ctx->imsi); - if(ue_ctx->eit == true) - { - pack_esm_information_request(reply_msg, ue_ctx); - m_s1ap_log->console("Sending ESM information request\n"); - } - else - { - //FIXME The packging of GTP-C messages is not ready. - //This means that GTP-U tunnels are created with function calls, as opposed to GTP-C. - m_mme_gtpc->send_create_session_request(ue_ctx->imsi, ue_ctx->mme_ue_s1ap_id); - } - return true; -} - -bool -s1ap::pack_esm_information_request(srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx) -{ - srslte::byte_buffer_t *nas_buffer = m_pool->allocate(); - - //Setup initiating message - LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu; - bzero(&tx_pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); - - tx_pdu.ext = false; - tx_pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE; - - LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *init = &tx_pdu.choice.initiatingMessage; - init->procedureCode = LIBLTE_S1AP_PROC_ID_DOWNLINKNASTRANSPORT; - init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DOWNLINKNASTRANSPORT; - - //Setup Dw NAS structure - LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT *dw_nas = &init->choice.DownlinkNASTransport; - dw_nas->ext=false; - dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = ue_ctx->mme_ue_s1ap_id;//FIXME Change name - dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ue_ctx->enb_ue_s1ap_id; - dw_nas->HandoverRestrictionList_present=false; - dw_nas->SubscriberProfileIDforRFP_present=false; - - LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT esm_info_req; - /*typedef struct{ - uint8 eps_bearer_id; - uint8 proc_transaction_id; - }LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT;*/ - esm_info_req.eps_bearer_id=0; - esm_info_req.proc_transaction_id = ue_ctx->procedure_transaction_id; - uint8_t sec_hdr_type=2; - - ue_ctx->security_ctxt.dl_nas_count++; - - LIBLTE_ERROR_ENUM err = srslte_mme_pack_esm_information_request_msg(&esm_info_req, sec_hdr_type,ue_ctx->security_ctxt.dl_nas_count,(LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); - if(err != LIBLTE_SUCCESS) - { - m_s1ap_log->error("Error packing ESM information request\n"); - m_s1ap_log->console("Error packing ESM information request\n"); - return false; - } - - uint8_t mac[4]; - srslte::security_128_eia1 (&ue_ctx->security_ctxt.k_nas_int[16], - ue_ctx->security_ctxt.dl_nas_count, - 0, - SECURITY_DIRECTION_DOWNLINK, - &nas_buffer->msg[5], - nas_buffer->N_bytes - 5, - mac - ); - - memcpy(&nas_buffer->msg[1],mac,4); - //Copy NAS PDU to Downlink NAS Trasport message buffer - memcpy(dw_nas->NAS_PDU.buffer, nas_buffer->msg, nas_buffer->N_bytes); - dw_nas->NAS_PDU.n_octets = nas_buffer->N_bytes; - - //Pack Downlink NAS Transport Message - err = liblte_s1ap_pack_s1ap_pdu(&tx_pdu, (LIBLTE_BYTE_MSG_STRUCT *) reply_msg); - if(err != LIBLTE_SUCCESS) - { - m_s1ap_log->error("Error packing Dw NAS Transport: Athentication Reject\n"); - m_s1ap_log->console("Error packing Downlink NAS Transport: Athentication Reject\n"); - return false; - } - - m_pool->deallocate(nas_buffer); - ssize_t n_sent = sctp_send(m_s1mme,reply_msg->msg, reply_msg->N_bytes, &ue_ctx->enb_sri, 0); - if(n_sent == -1) - { - m_s1ap_log->error("Failed to send NAS Attach Request"); - return false; - } - return true; -} - - -bool -s1ap::handle_esm_information_response(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t* ue_ctx) -{ - LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT esm_info_resp; - /* - typedef struct{ - LIBLTE_MME_ACCESS_POINT_NAME_STRUCT apn; - LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; - uint8 eps_bearer_id; - uint8 proc_transaction_id; - bool apn_present; - bool protocol_cnfg_opts_present; - }LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT;*/ - //Get NAS authentication response - LIBLTE_ERROR_ENUM err = srslte_mme_unpack_esm_information_response_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &esm_info_resp); - if(err != LIBLTE_SUCCESS){ - m_s1ap_log->error("Error unpacking NAS authentication response. Error: %s\n", liblte_error_text[err]); - return false; - } - m_s1ap_log->info("ESM Info: EPS bearer id %d\n",esm_info_resp.eps_bearer_id); - if(esm_info_resp.apn_present) - { - m_s1ap_log->info("ESM Info: APN %s\n",esm_info_resp.eps_bearer_id); - m_s1ap_log->console("ESM Info: APN %s\n",esm_info_resp.eps_bearer_id); - } - /* - m_pool->deallocate(nas_buffer); - ssize_t n_sent = sctp_send(m_s1mme,reply_msg->msg, reply_msg->N_bytes, &ue_ctx->enb_sri, 0); - if(n_sent == -1) - { - m_s1ap_log->error("Failed to send NAS Attach Request"); - return false; - } - */ - - //FIXME The packging of GTP-C messages is not ready. - //This means that GTP-U tunnels are created with function calls, as opposed to GTP-C. - m_mme_gtpc->send_create_session_request(ue_ctx->imsi, ue_ctx->mme_ue_s1ap_id); - return true; -} bool s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp, struct srslte::gtpc_f_teid_ie sgw_ctrl_fteid) { @@ -764,59 +485,6 @@ s1ap::handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSE return true; } -bool -s1ap::handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx) -{ - /* - typedef struct{ - LIBLTE_BYTE_MSG_STRUCT esm_msg; - }LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT; - */ - /* - typedef struct{ - LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; - uint8 eps_bearer_id; - uint8 proc_transaction_id; - bool protocol_cnfg_opts_present; - }LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT; - */ - LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT attach_comp; - uint8_t pd, msg_type; - srslte::byte_buffer_t *esm_msg = m_pool->allocate(); - LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT act_bearer; - - m_s1ap_log->info_hex(nas_msg->msg, nas_msg->N_bytes, "NAS Attach complte"); - - //Get NAS authentication response - LIBLTE_ERROR_ENUM err = liblte_mme_unpack_attach_complete_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &attach_comp); - if(err != LIBLTE_SUCCESS){ - m_s1ap_log->error("Error unpacking NAS authentication response. Error: %s\n", liblte_error_text[err]); - return false; - } - - // memcpy(esm_msg->msg, attach_comp.esm_msg.buffer, attach_comp.esm_msg.N_bytes); - //esm_msg->N_bytes = attach_comp.esm_msg.N_bytes; - - err = liblte_mme_unpack_activate_default_eps_bearer_context_accept_msg( (LIBLTE_BYTE_MSG_STRUCT *) &attach_comp.esm_msg, &act_bearer); - if(err != LIBLTE_SUCCESS){ - m_s1ap_log->error("Error unpacking Activate EPS Bearer Context Accept Msg. Error: %s\n", liblte_error_text[err]); - return false; - } - - m_s1ap_log->console("Unpacked Attached Complete Message\n"); - m_s1ap_log->console("Unpacked Activavate Default EPS Bearer message. EPS Bearer id %d\n",act_bearer.eps_bearer_id); - //ue_ctx->erabs_ctx[act_bearer->eps_bearer_id].enb_fteid; - if(act_bearer.eps_bearer_id < 5 || act_bearer.eps_bearer_id > 16) - { - m_s1ap_log->error("EPS Bearer ID out of range\n"); - return false; - } - m_mme_gtpc->send_modify_bearer_request(&ue_ctx->erabs_ctx[act_bearer.eps_bearer_id]); - return true; -} - - - bool s1ap::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri) { @@ -887,6 +555,20 @@ s1ap::add_new_enb_ctx(const enb_ctx_t &enb_ctx, const struct sctp_sndrcvinfo *en return; } +ue_ctx_t* +s1ap::find_ue_ctx(uint32_t mme_ue_s1ap_id) +{ + std::map::iterator it = m_active_ues.find(mme_ue_s1ap_id); + if(it == m_active_ues.end()) + { + return NULL; + } + else + { + return it->second; + } +} + void s1ap::add_new_ue_ctx(const ue_ctx_t &ue_ctx) { diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 56947b526..7e911fcc4 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -71,6 +71,7 @@ s1ap_nas_transport::init(void) m_pool = srslte::byte_buffer_pool::get_instance(); m_hss = hss::get_instance(); + m_mme_gtpc = mme_gtpc::get_instance(); } @@ -163,6 +164,220 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA return true; } +bool +s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, struct sctp_sndrcvinfo *enb_sri, srslte::byte_buffer_t *reply_buffer, bool *reply_flag) +{ + + bool ue_valid = true; + uint32_t enb_ue_s1ap_id = ul_xport->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; + uint32_t mme_ue_s1ap_id = ul_xport->MME_UE_S1AP_ID.MME_UE_S1AP_ID; + + m_s1ap_log->console("Received Uplink NAS Transport message.\n"); + m_s1ap_log->info("Received Uplink NAS Transport message.\n"); + + + ue_ctx_t *ue_ctx = m_s1ap->find_ue_ctx(mme_ue_s1ap_id); + if(ue_ctx == NULL) + { + //TODO UE not registered, send error message. + m_s1ap_log->warning("Could not find UE. MME-UE S1AP id: %lu\n",mme_ue_s1ap_id); + return false; + } + + m_s1ap_log->debug("Found UE. MME-UE S1AP id: %lu\n",mme_ue_s1ap_id); + + //Get NAS message type + uint8_t pd, msg_type; + srslte::byte_buffer_t *nas_msg = m_pool->allocate(); + + memcpy(nas_msg->msg, &ul_xport->NAS_PDU.buffer, ul_xport->NAS_PDU.n_octets); + nas_msg->N_bytes = ul_xport->NAS_PDU.n_octets; + liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &pd, &msg_type); + + switch (msg_type) { + case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE: + handle_nas_authentication_response(nas_msg, ue_ctx, reply_buffer, reply_flag); + m_s1ap_log->info("UL NAS: Received Authentication Response\n"); + break; + case LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMPLETE: + m_s1ap_log->info("UL NAS: Received Security Mode Complete\n"); + handle_nas_security_mode_complete(nas_msg, ue_ctx, reply_buffer, reply_flag); + return true; //no need for reply. FIXME this should be better structured... + break; + case LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE: + m_s1ap_log->info("UL NAS: Received Attach Complete\n"); + handle_nas_attach_complete(nas_msg, ue_ctx, reply_buffer, reply_flag); + ue_ctx->security_ctxt.ul_nas_count++; + return true; //no need for reply. FIXME this should be better structured... + break; + case LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_RESPONSE: + m_s1ap_log->info("UL NAS: Received ESM Information Response\n"); + handle_esm_information_response(nas_msg, ue_ctx, reply_buffer, reply_flag); + ue_ctx->security_ctxt.ul_nas_count++; + return true; + default: + m_s1ap_log->warning("Unhandled NAS message 0x%x\n", msg_type ); + m_s1ap_log->console("Unhandled NAS message 0x%x\n", msg_type ); + return false; //FIXME (nas_msg deallocate needs to be called) + } + + if(*reply_flag == true) + { + m_s1ap_log->info("DL NAS: Sent Downlink NAS message\n"); + m_s1ap_log->console("DL NAS: Sent Downlink NAs Message\n"); + } + m_pool->deallocate(nas_msg); + + return true; +} + +bool +s1ap_nas_transport::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_buffer, bool* reply_flag) +{ + + LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT auth_resp; + bool ue_valid=true; + + //Get NAS authentication response + LIBLTE_ERROR_ENUM err = liblte_mme_unpack_authentication_response_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &auth_resp); + if(err != LIBLTE_SUCCESS){ + m_s1ap_log->error("Error unpacking NAS authentication response. Error: %s\n", liblte_error_text[err]); + return false; + } + + for(int i=0; i<8;i++) + { + if(auth_resp.res[i] != ue_ctx->security_ctxt.xres[i]) + { + ue_valid = false; + } + } + if(!ue_valid) + { + std::cout<security_ctxt.xres[i]; + } + std::cout<console("UE Authentication Rejected. IMSI: %lu\n", ue_ctx->imsi); + m_s1ap_log->warning("UE Authentication Rejected. IMSI: %lu\n", ue_ctx->imsi); + //Send back Athentication Reject + pack_authentication_reject(reply_buffer, ue_ctx->enb_ue_s1ap_id, ue_ctx->mme_ue_s1ap_id); + *reply_flag = true; + return false; + } + else + { + m_s1ap_log->console("UE Authentication Accepted. IMSI: %lu\n", ue_ctx->imsi); + m_s1ap_log->info("UE Authentication Accepted. IMSI: %lu\n", ue_ctx->imsi); + //Send Security Mode Command + pack_security_mode_command(reply_buffer, ue_ctx); + *reply_flag = true; + } + return true; +} + +bool +s1ap_nas_transport::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag) +{ + LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT sm_comp; + + //Get NAS authentication response + LIBLTE_ERROR_ENUM err = liblte_mme_unpack_security_mode_complete_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &sm_comp); + if(err != LIBLTE_SUCCESS){ + m_s1ap_log->error("Error unpacking NAS authentication response. Error: %s\n", liblte_error_text[err]); + return false; + } + + //TODO Check integrity + + //TODO Handle imeisv + if(sm_comp.imeisv_present) + { + m_s1ap_log->warning("IMEI-SV present but not handled"); + } + + m_s1ap_log->info("Received Security Mode Command Complete. IMSI: %lu\n", ue_ctx->imsi); + m_s1ap_log->console("Received Security Mode Command Complete. IMSI: %lu\n", ue_ctx->imsi); + if(ue_ctx->eit == true) + { + pack_esm_information_request(reply_buffer, ue_ctx); + m_s1ap_log->console("Sending ESM information request\n"); + *reply_flag = true; + } + else + { + //FIXME The packging of GTP-C messages is not ready. + //This means that GTP-U tunnels are created with function calls, as opposed to GTP-C. + m_mme_gtpc->send_create_session_request(ue_ctx->imsi, ue_ctx->mme_ue_s1ap_id); + *reply_flag = false; //No reply needed + } + return true; +} + +bool +s1ap_nas_transport::handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag) +{ + + LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT attach_comp; + uint8_t pd, msg_type; + srslte::byte_buffer_t *esm_msg = m_pool->allocate(); + LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT act_bearer; + + m_s1ap_log->info_hex(nas_msg->msg, nas_msg->N_bytes, "NAS Attach complte"); + + //Get NAS authentication response + LIBLTE_ERROR_ENUM err = liblte_mme_unpack_attach_complete_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &attach_comp); + if(err != LIBLTE_SUCCESS){ + m_s1ap_log->error("Error unpacking NAS authentication response. Error: %s\n", liblte_error_text[err]); + return false; + } + + err = liblte_mme_unpack_activate_default_eps_bearer_context_accept_msg( (LIBLTE_BYTE_MSG_STRUCT *) &attach_comp.esm_msg, &act_bearer); + if(err != LIBLTE_SUCCESS){ + m_s1ap_log->error("Error unpacking Activate EPS Bearer Context Accept Msg. Error: %s\n", liblte_error_text[err]); + return false; + } + + m_s1ap_log->console("Unpacked Attached Complete Message\n"); + m_s1ap_log->console("Unpacked Activavate Default EPS Bearer message. EPS Bearer id %d\n",act_bearer.eps_bearer_id); + //ue_ctx->erabs_ctx[act_bearer->eps_bearer_id].enb_fteid; + if(act_bearer.eps_bearer_id < 5 || act_bearer.eps_bearer_id > 16) + { + m_s1ap_log->error("EPS Bearer ID out of range\n"); + return false; + } + m_mme_gtpc->send_modify_bearer_request(&ue_ctx->erabs_ctx[act_bearer.eps_bearer_id]); + return true; +} + +bool +s1ap_nas_transport::handle_esm_information_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag) +{ + LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT esm_info_resp; + + //Get NAS authentication response + LIBLTE_ERROR_ENUM err = srslte_mme_unpack_esm_information_response_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &esm_info_resp); + if(err != LIBLTE_SUCCESS){ + m_s1ap_log->error("Error unpacking NAS authentication response. Error: %s\n", liblte_error_text[err]); + return false; + } + m_s1ap_log->info("ESM Info: EPS bearer id %d\n",esm_info_resp.eps_bearer_id); + if(esm_info_resp.apn_present) + { + m_s1ap_log->info("ESM Info: APN %s\n",esm_info_resp.eps_bearer_id); + m_s1ap_log->console("ESM Info: APN %s\n",esm_info_resp.eps_bearer_id); + } + + //FIXME The packging of GTP-C messages is not ready. + //This means that GTP-U tunnels are created with function calls, as opposed to GTP-C. + m_mme_gtpc->send_create_session_request(ue_ctx->imsi, ue_ctx->mme_ue_s1ap_id); + return true; +} + /*Packing/Unpacking helper functions*/ bool @@ -446,7 +661,74 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, m_pool->deallocate(nas_buffer); return true; } + +bool +s1ap_nas_transport::pack_esm_information_request(srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx) +{ + srslte::byte_buffer_t *nas_buffer = m_pool->allocate(); + + //Setup initiating message + LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu; + bzero(&tx_pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); + + tx_pdu.ext = false; + tx_pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE; + + LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *init = &tx_pdu.choice.initiatingMessage; + init->procedureCode = LIBLTE_S1AP_PROC_ID_DOWNLINKNASTRANSPORT; + init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DOWNLINKNASTRANSPORT; + + //Setup Dw NAS structure + LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT *dw_nas = &init->choice.DownlinkNASTransport; + dw_nas->ext=false; + dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = ue_ctx->mme_ue_s1ap_id;//FIXME Change name + dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ue_ctx->enb_ue_s1ap_id; + dw_nas->HandoverRestrictionList_present=false; + dw_nas->SubscriberProfileIDforRFP_present=false; + + LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT esm_info_req; + esm_info_req.eps_bearer_id=0; + esm_info_req.proc_transaction_id = ue_ctx->procedure_transaction_id; + uint8_t sec_hdr_type=2; + ue_ctx->security_ctxt.dl_nas_count++; + + LIBLTE_ERROR_ENUM err = srslte_mme_pack_esm_information_request_msg(&esm_info_req, sec_hdr_type,ue_ctx->security_ctxt.dl_nas_count,(LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + if(err != LIBLTE_SUCCESS) + { + m_s1ap_log->error("Error packing ESM information request\n"); + m_s1ap_log->console("Error packing ESM information request\n"); + return false; + } + + uint8_t mac[4]; + srslte::security_128_eia1 (&ue_ctx->security_ctxt.k_nas_int[16], + ue_ctx->security_ctxt.dl_nas_count, + 0, + SECURITY_DIRECTION_DOWNLINK, + &nas_buffer->msg[5], + nas_buffer->N_bytes - 5, + mac + ); + + memcpy(&nas_buffer->msg[1],mac,4); + //Copy NAS PDU to Downlink NAS Trasport message buffer + memcpy(dw_nas->NAS_PDU.buffer, nas_buffer->msg, nas_buffer->N_bytes); + dw_nas->NAS_PDU.n_octets = nas_buffer->N_bytes; + + //Pack Downlink NAS Transport Message + err = liblte_s1ap_pack_s1ap_pdu(&tx_pdu, (LIBLTE_BYTE_MSG_STRUCT *) reply_msg); + if(err != LIBLTE_SUCCESS) + { + m_s1ap_log->error("Error packing Dw NAS Transport: Athentication Reject\n"); + m_s1ap_log->console("Error packing Downlink NAS Transport: Athentication Reject\n"); + return false; + } + + m_pool->deallocate(nas_buffer); + return true; +} + /*Helper functions*/ From c3f0753a93cd0cdb6a520cb25bd6eb00f0f2fd5f Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 21 Dec 2017 06:46:37 +0000 Subject: [PATCH 141/172] Adding some cleaning up functionality at the SPGW. --- srsepc/src/spgw/spgw.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index b9774ffb9..01592286f 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -140,6 +140,14 @@ spgw::stop() close(m_s1u); } } + std::map::iterator it = m_teid_to_tunnel_ctx.begin(); //Map control TEID to tunnel ctx. Usefull to get reply ctrl TEID, UE IP, etc. + while(it!=m_teid_to_tunnel_ctx.end()) + { + m_spgw_log->info("Deleting SP-GW Tunnel. IMSI: %lu\n", it->second->imsi); + m_spgw_log->console("Deleting SP-GW Tunnel. IMSI: %lu\n", it->second->imsi); + delete it->second; + m_teid_to_tunnel_ctx.erase(it++); + } return; } From 8c9704ef3cc95913229569026822e09654407007 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 21 Dec 2017 18:48:31 +0000 Subject: [PATCH 142/172] Adding delete session request. --- lib/include/srslte/asn1/gtpc.h | 2 ++ lib/include/srslte/asn1/gtpc_msg.h | 33 +++++++++++++++++++++++ srsepc/hdr/mme/mme_gtpc.h | 1 + srsepc/hdr/spgw/spgw.h | 1 + srsepc/src/mme/mme_gtpc.cc | 34 ++++++++++++++++++++++++ srsepc/src/mme/s1ap.cc | 17 ++++++++++-- srsepc/src/spgw/spgw.cc | 42 ++++++++++++++++++++++++------ 7 files changed, 120 insertions(+), 10 deletions(-) diff --git a/lib/include/srslte/asn1/gtpc.h b/lib/include/srslte/asn1/gtpc.h index 23a4d7118..aca57a4bf 100644 --- a/lib/include/srslte/asn1/gtpc.h +++ b/lib/include/srslte/asn1/gtpc.h @@ -76,6 +76,8 @@ typedef union gtpc_msg_choice struct gtpc_create_session_response create_session_response; struct gtpc_modify_bearer_request modify_bearer_request; struct gtpc_modify_bearer_response modify_bearer_response; + struct gtpc_delete_session_request delete_session_request; + struct gtpc_delete_session_response delete_session_response; } gtpc_msg_choice_t; /**************************************************************************** diff --git a/lib/include/srslte/asn1/gtpc_msg.h b/lib/include/srslte/asn1/gtpc_msg.h index efd2a2290..4271b064d 100644 --- a/lib/include/srslte/asn1/gtpc_msg.h +++ b/lib/include/srslte/asn1/gtpc_msg.h @@ -377,5 +377,38 @@ struct gtpc_modify_bearer_response //ext }; +/**************************************************************************** + * + * GTP-C v2 Delete Session Resquest + * Ref: 3GPP TS 29.274 v10.14.0 Table 7.2.9.1-1 + * + ***************************************************************************/ + +struct gtpc_delete_session_request +{ + struct gtpc_cause_ie cause; + //Linked EPS Bearer ID + //User Location Information + //Indication Flags + //Protocol Configuration Options + //Originating Node + //Private extension +}; + +/**************************************************************************** + * + * GTP-C v2 Delete Session Response + * Ref: 3GPP TS 29.274 v10.14.0 Table 7.2.10.1-1 + * + ***************************************************************************/ + +struct gtpc_delete_session_response +{ + struct gtpc_cause_ie cause; + //Recovery + //Protocol Configuration Options + //Private extension +}; + } //namespace #endif //GTPC_V2_MSG_H diff --git a/srsepc/hdr/mme/mme_gtpc.h b/srsepc/hdr/mme/mme_gtpc.h index 2c4cb10c9..f2804e22b 100644 --- a/srsepc/hdr/mme/mme_gtpc.h +++ b/srsepc/hdr/mme/mme_gtpc.h @@ -52,6 +52,7 @@ public: void handle_create_session_response(srslte::gtpc_pdu *cs_resp_pdu); void send_modify_bearer_request(erab_ctx_t *bearer_ctx); void handle_modify_bearer_response(srslte::gtpc_pdu *mb_resp_pdu); + void send_delete_session_request(ue_ctx_t *ue_ctx); private: diff --git a/srsepc/hdr/spgw/spgw.h b/srsepc/hdr/spgw/spgw.h index 047a5db9a..095b4d9b0 100644 --- a/srsepc/hdr/spgw/spgw.h +++ b/srsepc/hdr/spgw/spgw.h @@ -75,6 +75,7 @@ public: void handle_create_session_request(struct srslte::gtpc_create_session_request *cs_req, struct srslte::gtpc_pdu *cs_resp_pdu); void handle_modify_bearer_request(struct srslte::gtpc_pdu *mb_req_pdu, struct srslte::gtpc_pdu *mb_resp_pdu); + void handle_delete_session_request(struct srslte::gtpc_pdu *del_req_pdu, struct srslte::gtpc_pdu *del_resp_pdu); void handle_sgi_pdu(srslte::byte_buffer_t *msg); void handle_s1u_pdu(srslte::byte_buffer_t *msg); diff --git a/srsepc/src/mme/mme_gtpc.cc b/srsepc/src/mme/mme_gtpc.cc index 4d7a0aee9..ade0a0687 100644 --- a/srsepc/src/mme/mme_gtpc.cc +++ b/srsepc/src/mme/mme_gtpc.cc @@ -212,4 +212,38 @@ mme_gtpc::handle_modify_bearer_response(srslte::gtpc_pdu *mb_resp_pdu) return; } +void +mme_gtpc::send_delete_session_request(ue_ctx_t *ue_ctx) +{ + m_mme_gtpc_log->info("Sending GTP-C Delete Session Request request\n"); + srslte::gtpc_pdu del_req_pdu; + srslte::gtpc_f_teid_ie *sgw_ctrl_fteid; + + //FIXME the UE control TEID sould be stored in the UE ctxt, not in the E-RAB ctxt + //Maybe a mme_s1ap_id to ctrl teid map as well? + + for(int i = 0; ierabs_ctx[i].state != ERAB_DEACTIVATED) + { + sgw_ctrl_fteid = &ue_ctx->erabs_ctx[i].sgw_ctrl_fteid; + break; + } + } + + srslte::gtpc_header *header = &del_req_pdu.header; + header->teid_present = true; + header->teid = sgw_ctrl_fteid->teid; + header->type = srslte::GTPC_MSG_TYPE_DELETE_SESSION_REQUEST; + + srslte::gtpc_delete_session_request *del_req = &del_req_pdu.choice.delete_session_request; + del_req->cause.cause_value = srslte::GTPC_CAUSE_VALUE_ISR_DEACTIVATION; + m_mme_gtpc_log->info("GTP-C Delete Session Request -- S-GW Control TEID %d\n", sgw_ctrl_fteid->teid ); + + srslte::gtpc_pdu del_resp_pdu; + m_spgw->handle_delete_session_request(&del_req_pdu, &del_resp_pdu); + + //TODO Handle delete session response + return; +} } //namespace srsepc diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 322ae165b..e7650e871 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -506,7 +506,7 @@ s1ap::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQU { m_s1ap_log->error("Could not find eNB for this request.\n"); return false; - } + } uint16_t enb_id = it->second; std::map >::iterator ue_set = m_enb_id_to_ue_ids.find(enb_id); if(ue_set == m_enb_id_to_ue_ids.end()) @@ -517,7 +517,20 @@ s1ap::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQU ue_set->second.erase(mme_ue_s1ap_id); //Delete any context at the SPGW - //m_spgw->delete_session_request(ue_ctx->imsi); + bool active = false; + for(int i=0;isecond->erabs_ctx[i].state != ERAB_DEACTIVATED) + { + active = true; + break; + } + } + if(active == true) + { + //There are active E-RABs, send delete session request + m_mme_gtpc->send_delete_session_request(ue_ctx->second); + } //Delete UE context delete ue_ctx->second; diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index 01592286f..c4064d695 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -375,7 +375,7 @@ spgw::handle_sgi_pdu(srslte::byte_buffer_t *msg) int n = sendto(m_s1u,msg->msg,msg->N_bytes,0,(struct sockaddr*) &enb_addr,sizeof(enb_addr)); if(n<0) { - m_spgw_log->console("Error sending packet to eNB\n"); + m_spgw_log->error("Error sending packet to eNB\n"); return; } //m_spgw_log->console("Sent packet to %s:%d. Bytes=%d\n",inet_ntoa(enb_addr.sin_addr), GTPU_RX_PORT,n); @@ -437,7 +437,8 @@ spgw::handle_create_session_request(struct srslte::gtpc_create_session_request * in_addr_t ue_ip = get_new_ue_ipv4(); uint8_t default_bearer_id = 5; - //Save the UE IP to User TEID map //TODO!!! + + //Save the UE IP to User TEID map spgw_tunnel_ctx_t *tunnel_ctx = new spgw_tunnel_ctx_t; tunnel_ctx->imsi = cs_req->imsi; tunnel_ctx->ebi = default_bearer_id; @@ -449,6 +450,7 @@ spgw::handle_create_session_request(struct srslte::gtpc_create_session_request * tunnel_ctx->up_ctrl_fteid.teid = spgw_uplink_ctrl_teid; tunnel_ctx->ue_ipv4 = ue_ip; m_teid_to_tunnel_ctx.insert(std::pair(spgw_uplink_ctrl_teid,tunnel_ctx)); + //Create session response message //Setup GTP-C header header->piggyback = false; @@ -479,13 +481,9 @@ spgw::handle_create_session_request(struct srslte::gtpc_create_session_request * return; } - /* -void -spgw::delete_session_request(uint64_t imsi) -{ -} - */ + + void spgw::handle_modify_bearer_request(struct srslte::gtpc_pdu *mb_req_pdu, struct srslte::gtpc_pdu *mb_resp_pdu) { @@ -541,4 +539,32 @@ spgw::handle_modify_bearer_request(struct srslte::gtpc_pdu *mb_req_pdu, struct s printf("%d %d\n",mb_resp->eps_bearer_context_modified.ebi, tunnel_ctx->ebi); mb_resp->eps_bearer_context_modified.cause.cause_value = srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED; } + +void +spgw::handle_delete_session_request(struct srslte::gtpc_pdu *del_req_pdu, struct srslte::gtpc_pdu *del_resp_pdu) +{ + //Find tunel ctxt + uint32_t ctrl_teid = del_req_pdu->header.teid; + std::map::iterator tunnel_it = m_teid_to_tunnel_ctx.find(ctrl_teid); + if(tunnel_it == m_teid_to_tunnel_ctx.end()) + { + m_spgw_log->warning("Could not find TEID %d to delete\n",ctrl_teid); + return; + } + spgw_tunnel_ctx_t *tunnel_ctx = tunnel_it->second; + in_addr_t ue_ipv4 = tunnel_ctx->ue_ipv4; + + //Delete data tunnel + pthread_mutex_lock(&m_mutex); + std::map::iterator data_it = m_ip_to_teid.find(tunnel_ctx->ue_ipv4); + if(data_it != m_ip_to_teid.end()) + { + m_ip_to_teid.erase(data_it); + } + pthread_mutex_unlock(&m_mutex); + + delete tunnel_ctx; + return; +} + } //namespace srsepc From ce78d895d57f54a2cbb3f4b80340ca0a67b9e427 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 21 Dec 2017 20:13:32 +0000 Subject: [PATCH 143/172] Small bug fix --- srsepc/src/spgw/spgw.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index c4064d695..23cf2a66c 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -562,6 +562,7 @@ spgw::handle_delete_session_request(struct srslte::gtpc_pdu *del_req_pdu, struct m_ip_to_teid.erase(data_it); } pthread_mutex_unlock(&m_mutex); + m_teid_to_tunnel_ctx.erase(tunnel_it); delete tunnel_ctx; return; From 05604ec6ebd5845fa79b5c356a89e666fb250374 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 22 Dec 2017 00:14:42 +0000 Subject: [PATCH 144/172] Added UML diagram to docs --- srsepc/docs/source/_imgs/epc-uml.svg | 1612 ++++++++++++++++++++++++++ srsepc/docs/source/epc_design.rst | 30 +- srsepc/hdr/mme/s1ap.h | 13 +- 3 files changed, 1619 insertions(+), 36 deletions(-) create mode 100644 srsepc/docs/source/_imgs/epc-uml.svg diff --git a/srsepc/docs/source/_imgs/epc-uml.svg b/srsepc/docs/source/_imgs/epc-uml.svg new file mode 100644 index 000000000..75aa8aaf0 --- /dev/null +++ b/srsepc/docs/source/_imgs/epc-uml.svg @@ -0,0 +1,1612 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/srsepc/docs/source/epc_design.rst b/srsepc/docs/source/epc_design.rst index 3a1280c99..17861938f 100644 --- a/srsepc/docs/source/epc_design.rst +++ b/srsepc/docs/source/epc_design.rst @@ -6,31 +6,13 @@ Code Structure The LTE library should include the following functionality that will be common accress multiple nodes. -.. blockdiag:: +.. _epc-overall: - blockdiag { - srsLTE -> lib -> src -> upper -> gtpu.cc; - upper -> gtpc.cc; - upper -> s1app.cc; - upper -> diameter.cc; - src -> asn1; - } +.. figure:: _imgs/epc-uml.svg + + EPC overall class architecture -The examples should aim to include the following classes - -.. blockdiag:: - - blockdiag { - srsLTE -> srsepc -> src -> mme -> mme.cc; - mme -> main.cc; - src -> hss -> hss.cc; - hss -> main.cc; - src -> spgw -> spgw.cc; - spgw -> main.cc; - srsepc -> src -> main.cc; - src -> epc.cc; - } MME Design @@ -43,8 +25,6 @@ The main loop of the MME will HSS Design ********** -S-GW Design +SP-GW Design *********** -P-GW Design -*********** diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 36c4d148e..5dff3a966 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -68,22 +68,13 @@ public: bool handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb_sri); bool handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri); - - bool handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, struct sctp_sndrcvinfo *enb_sri); - bool handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, struct sctp_sndrcvinfo *enb_sri); - bool handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri); - - bool handle_nas_authentication_response(srslte::byte_buffer_t *nas_buffer, srslte::byte_buffer_t *reply_buffer, ue_ctx_t *ue_ctx); - bool handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx); - bool send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp, struct srslte::gtpc_f_teid_ie sgw_ctrl_fteid); bool handle_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *msg); + bool handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri); + bool send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp, struct srslte::gtpc_f_teid_ie sgw_ctrl_fteid); bool handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *in_ctxt_resp); - bool handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx); void activate_eps_bearer(uint32_t mme_s1ap_id, uint8_t ebi); - bool pack_esm_information_request(srslte::byte_buffer_t* reply_msg, srsepc::ue_ctx_t* ue_ctx); - bool handle_esm_information_response(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t* ue_ctx); void print_enb_ctx_info(const std::string &prefix, const enb_ctx_t &enb_ctx); From c5b1b7edc323fa205a8dc60dd49afbb7904d6ba7 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 22 Dec 2017 16:11:51 +0000 Subject: [PATCH 145/172] Continuing to cleanup. moving procedures to ctx_mngmt_proc. --- srsepc/hdr/mme/s1ap.h | 3 + srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h | 67 ++++++ srsepc/src/mme/s1ap.cc | 40 +++- srsepc/src/mme/s1ap_ctx_mngmt_proc.cc | 295 ++++++++++++++++++++++++++ 4 files changed, 404 insertions(+), 1 deletion(-) create mode 100644 srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h create mode 100644 srsepc/src/mme/s1ap_ctx_mngmt_proc.cc diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 5dff3a966..93ded1b46 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -43,6 +43,7 @@ #include "mme/s1ap_common.h" #include "mme/s1ap_mngmt_proc.h" #include "mme/s1ap_nas_transport.h" +#include "mme/s1ap_ctx_mngmt_proc.h" #include "mme/mme_gtpc.h" #include "hss/hss.h" @@ -84,6 +85,7 @@ public: void add_new_enb_ctx(const enb_ctx_t &enb_ctx, const struct sctp_sndrcvinfo* enb_sri); ue_ctx_t* find_ue_ctx(uint32_t mme_ue_s1ap_id); void add_new_ue_ctx(const ue_ctx_t &ue_ctx); + bool delete_ue_ctx(ue_ctx_t *ue_ctx); s1ap_args_t m_s1ap_args; srslte::log_filter *m_s1ap_log; @@ -107,6 +109,7 @@ private: s1ap_mngmt_proc* m_s1ap_mngmt_proc; s1ap_nas_transport* m_s1ap_nas_transport; + s1ap_ctx_mngmt_proc* m_s1ap_ctx_mngmt_proc; //FIXME the GTP-C should be moved to the MME class, the the packaging of GTP-C messages is done. mme_gtpc *m_mme_gtpc; diff --git a/srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h b/srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h new file mode 100644 index 000000000..259052b74 --- /dev/null +++ b/srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h @@ -0,0 +1,67 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ +#ifndef S1AP_CTX_MNGMT_PROC_H +#define S1AP_CTX_MNGMT_PROC_H + +#include "srslte/asn1/liblte_s1ap.h" +#include "srslte/common/common.h" +#include "mme/s1ap_common.h" +#include "srslte/common/log_filter.h" +#include "mme/mme_gtpc.h" + +namespace srsepc{ + +class s1ap; + +class s1ap_ctx_mngmt_proc +{ +public: + + static s1ap_ctx_mngmt_proc *m_instance; + static s1ap_ctx_mngmt_proc* get_instance(void); + static void cleanup(void); + + void init(void); + + bool send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp, struct srslte::gtpc_f_teid_ie sgw_ctrl_fteid); + bool handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *in_ctxt_resp, struct sctp_sndrcvinfo *enb_sri, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); + bool handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); + +private: + s1ap_ctx_mngmt_proc(); + virtual ~s1ap_ctx_mngmt_proc(); + + s1ap* m_s1ap; + srslte::log_filter *m_s1ap_log; + + s1ap_args_t m_s1ap_args; + + mme_gtpc* m_mme_gtpc; +}; + +} //namespace srsepc + +#endif //S1AP_MNGMT_PROC diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index e7650e871..55b431411 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -78,10 +78,13 @@ s1ap::init(s1ap_args_t s1ap_args, srslte::log_filter *s1ap_log) m_s1ap_log = s1ap_log; //Init message handlers - m_s1ap_mngmt_proc = s1ap_mngmt_proc::get_instance(); //Managment procedures (TS ) + m_s1ap_mngmt_proc = s1ap_mngmt_proc::get_instance(); //Managment procedures m_s1ap_mngmt_proc->init(); m_s1ap_nas_transport = s1ap_nas_transport::get_instance(); //NAS Transport procedures m_s1ap_nas_transport->init(); + m_s1ap_ctx_mngmt_proc = s1ap_ctx_mngmt_proc::get_instance(); //Context Management Procedures + m_s1ap_ctx_mngmt_proc->init(); + //Get pointer to the HSS m_hss = hss::get_instance(); @@ -115,6 +118,7 @@ s1ap::stop() //Cleanup message handlers s1ap_mngmt_proc::cleanup(); s1ap_nas_transport::cleanup(); + s1ap_ctx_mngmt_proc::cleanup(); return; } @@ -539,6 +543,40 @@ s1ap::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQU return true; } +bool +s1ap::delete_ue_ctx(ue_ctx_t *ue_ctx) +{ + uint32_t mme_ue_s1ap_id = ue_ctx->mme_ue_s1ap_id; + std::map::iterator ue_ctx_it = m_active_ues.find(mme_ue_s1ap_id); + if(ue_ctx_it == m_active_ues.end() ) + { + m_s1ap_log->info("UE not found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); + return false; + } + + //Delete UE within eNB UE set + std::map::iterator it = m_sctp_to_enb_id.find(ue_ctx->enb_sri.sinfo_assoc_id); + if(it == m_sctp_to_enb_id.end() ) + { + m_s1ap_log->error("Could not find eNB for this request.\n"); + return false; + } + uint16_t enb_id = it->second; + std::map >::iterator ue_set = m_enb_id_to_ue_ids.find(enb_id); + if(ue_set == m_enb_id_to_ue_ids.end()) + { + m_s1ap_log->error("Could not find the eNB's UEs.\n"); + return false; + } + ue_set->second.erase(mme_ue_s1ap_id); + + //Delete UE context + delete ue_ctx; + m_active_ues.erase(ue_ctx_it); + m_s1ap_log->info("Deleted UE Context.\n"); + + return true; +} enb_ctx_t* s1ap::find_enb_ctx(uint16_t enb_id) diff --git a/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc new file mode 100644 index 000000000..603b80b34 --- /dev/null +++ b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc @@ -0,0 +1,295 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +//#include "srslte/upper/s1ap_common.h" +#include "srslte/common/bcd_helpers.h" +#include "mme/s1ap.h" +#include "mme/s1ap_ctx_mngmt_proc.h" + +namespace srsepc{ + +s1ap_ctx_mngmt_proc* s1ap_ctx_mngmt_proc::m_instance = NULL; +boost::mutex s1ap_ctx_mngmt_proc_instance_mutex; + + +s1ap_ctx_mngmt_proc::s1ap_ctx_mngmt_proc() +{ +} + +s1ap_ctx_mngmt_proc::~s1ap_ctx_mngmt_proc() +{ +} + +s1ap_ctx_mngmt_proc* +s1ap_ctx_mngmt_proc::get_instance(void) +{ + boost::mutex::scoped_lock lock(s1ap_ctx_mngmt_proc_instance_mutex); + if(NULL == m_instance) { + m_instance = new s1ap_ctx_mngmt_proc(); + } + return(m_instance); +} + +void +s1ap_ctx_mngmt_proc::cleanup(void) +{ + boost::mutex::scoped_lock lock(s1ap_ctx_mngmt_proc_instance_mutex); + if(NULL != m_instance) { + delete m_instance; + m_instance = NULL; + } +} + +void +s1ap_ctx_mngmt_proc::init(void) +{ + m_s1ap = s1ap::get_instance(); + m_mme_gtpc = mme_gtpc::get_instance(); + m_s1ap_log = m_s1ap->m_s1ap_log; + m_s1ap_args = m_s1ap->m_s1ap_args; +} + +bool +s1ap_ctx_mngmt_proc::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp, struct srslte::gtpc_f_teid_ie sgw_ctrl_fteid) +{ + ue_ctx_t *ue_ctx; + + //Prepare reply PDU + LIBLTE_S1AP_S1AP_PDU_STRUCT pdu; + bzero(&pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); + pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE; + + LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *init = &pdu.choice.initiatingMessage; + init->procedureCode = LIBLTE_S1AP_PROC_ID_INITIALCONTEXTSETUP; + init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_INITIALCONTEXTSETUPREQUEST; + + LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT *in_ctxt_req = &init->choice.InitialContextSetupRequest; + + LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT *erab_ctxt = &in_ctxt_req->E_RABToBeSetupListCtxtSUReq.buffer[0]; //FIXME support more than one erab + srslte::byte_buffer_t *reply_buffer = m_pool->allocate(); + + m_s1ap_log->info("Preparing to send Initial Context Setup request\n"); + + //Find UE Context + std::map::iterator ue_ctx_it = m_active_ues.find(mme_ue_s1ap_id); + if(ue_ctx_it == m_active_ues.end()) + { + m_s1ap_log->error("Could not find UE to send Setup Context Request. MME S1AP Id: %d", mme_ue_s1ap_id); + return false; + } + ue_ctx = ue_ctx_it->second; + + //Add MME and eNB S1AP Ids + in_ctxt_req->MME_UE_S1AP_ID.MME_UE_S1AP_ID = ue_ctx->mme_ue_s1ap_id; + in_ctxt_req->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ue_ctx->enb_ue_s1ap_id; + + //Set UE-AMBR + in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL.BitRate=1000000000;//2^32-1 + in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL.BitRate=1000000000;//FIXME Get UE-AMBR from HSS + + //Setup eRAB context + in_ctxt_req->E_RABToBeSetupListCtxtSUReq.len = 1; + erab_ctxt->e_RAB_ID.E_RAB_ID = cs_resp->eps_bearer_context_created.ebi; + //Setup E-RAB QoS parameters + erab_ctxt->e_RABlevelQoSParameters.qCI.QCI = 9; + erab_ctxt->e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel.PriorityLevel = 15 ;//Lowest + erab_ctxt->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability = LIBLTE_S1AP_PRE_EMPTIONCAPABILITY_SHALL_NOT_TRIGGER_PRE_EMPTION; + erab_ctxt->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability = LIBLTE_S1AP_PRE_EMPTIONVULNERABILITY_PRE_EMPTABLE; + + erab_ctxt->e_RABlevelQoSParameters.gbrQosInformation_present=false; + + //Set E-RAB S-GW F-TEID + if (cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid_present == false){ + m_s1ap_log->error("Did not receive S1-U TEID in create session response\n"); + return false; + } + erab_ctxt->transportLayerAddress.n_bits = 32; //IPv4 + uint32_t sgw_s1u_ip = htonl(cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.ipv4); + //uint32_t sgw_s1u_ip = cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.ipv4; + uint8_t *tmp_ptr = erab_ctxt->transportLayerAddress.buffer; + liblte_value_2_bits(sgw_s1u_ip, &tmp_ptr, 32);//FIXME consider ipv6 + + uint32_t tmp_teid = cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.teid; + memcpy(erab_ctxt->gTP_TEID.buffer, &tmp_teid, sizeof(uint32_t)); + + //Set UE security capabilities and k_enb + bzero(in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer,sizeof(uint8_t)*16); + bzero(in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer,sizeof(uint8_t)*16); + for(int i = 0; i<3; i++) + { + if(ue_ctx->ue_network_cap.eea[i+1] == true) + { + in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer[i] = 1; //EEA supported + } + else + { + in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer[i] = 0; //EEA not supported + } + if(ue_ctx->ue_network_cap.eia[i+1] == true) + { + in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[i] = 1; //EEA supported + } + else + { + in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[i] = 0; //EEA not supported + } + // in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[0] = 1; //EIA1 + } + uint8_t key_enb[32]; + liblte_security_generate_k_enb(ue_ctx->security_ctxt.k_asme, ue_ctx->security_ctxt.ul_nas_count, key_enb); + liblte_unpack(key_enb, 32, in_ctxt_req->SecurityKey.buffer); + m_s1ap_log->info("Generating KeNB with UL NAS COUNT: %d\n",ue_ctx->security_ctxt.ul_nas_count); + //Set Attach accepted and activat default bearer NAS messages + if(cs_resp->paa_present != true) + { + m_s1ap_log->error("PAA not present\n"); + return false; + } + if(cs_resp->paa.pdn_type != srslte::GTPC_PDN_TYPE_IPV4) + { + m_s1ap_log->error("IPv6 not supported yet\n"); + return false; + } + srslte::byte_buffer_t *nas_buffer = m_pool->allocate(); + m_s1ap_nas_transport->pack_attach_accept(ue_ctx, erab_ctxt, &cs_resp->paa, nas_buffer); + + + LIBLTE_ERROR_ENUM err = liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)reply_buffer); + if(err != LIBLTE_SUCCESS) + { + m_s1ap_log->error("Could not pack Initial Context Setup Request Message\n"); + return false; + } + //Send Reply to eNB + ssize_t n_sent = sctp_send(m_s1mme,reply_buffer->msg, reply_buffer->N_bytes, &ue_ctx->enb_sri, 0); + if(n_sent == -1) + { + m_s1ap_log->error("Failed to send Initial Context Setup Request\n"); + return false; + } + + //Change E-RAB state to Context Setup Requested and save S-GW control F-TEID + ue_ctx->erabs_ctx[erab_ctxt->e_RAB_ID.E_RAB_ID].state = ERAB_CTX_REQUESTED; + ue_ctx->erabs_ctx[erab_ctxt->e_RAB_ID.E_RAB_ID].sgw_ctrl_fteid.teid = sgw_ctrl_fteid.teid; + ue_ctx->erabs_ctx[erab_ctxt->e_RAB_ID.E_RAB_ID].sgw_ctrl_fteid.ipv4 = sgw_ctrl_fteid.ipv4; + + struct in_addr addr; + addr.s_addr = sgw_s1u_ip; + m_s1ap_log->info("Sent Intial Context Setup Request. E-RAB id %d \n",erab_ctxt->e_RAB_ID.E_RAB_ID); + m_s1ap_log->info("Initial Context -- S1-U TEID 0x%x. IP %s \n", tmp_teid,inet_ntoa(addr)); + m_s1ap_log->console("Sent Intial Context Setup Request, E-RAB id %d\n",erab_ctxt->e_RAB_ID.E_RAB_ID); + m_s1ap_log->console("Initial Context -- S1-U TEID 0x%x. IP %s \n", tmp_teid,inet_ntoa(addr)); + + m_pool->deallocate(reply_buffer); + m_pool->deallocate(nas_buffer); + return true; +} + +bool +s1ap_ctx_mngmt_proc::handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *in_ctxt_resp, struct sctp_sndrcvinfo *enb_sri, srslte::byte_buffer_t *reply_buffer, bool *reply_flag) +{ + + uint32_t mme_ue_s1ap_id = in_ctxt_resp->MME_UE_S1AP_ID.MME_UE_S1AP_ID; + ue_ctx_t *ue_ctx = m_s1ap->find_ue_ctx(mme_ue_s1ap_id); + if (ue_ctx == NULL) + { + m_s1ap_log->error("Could not find UE's context in active UE's map\n"); + return false; + } + + //Setup E-RABs + for(uint32_t i=0; iE_RABSetupListCtxtSURes.len;i++) + { + uint8_t erab_id = in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].e_RAB_ID.E_RAB_ID; + erab_ctx_t *erab_ctx = &ue_ctx->erabs_ctx[erab_id]; + if (erab_ctx->state != ERAB_CTX_REQUESTED) + { + m_s1ap_log->error("E-RAB requested was not active %d\n",erab_id); + return false; + } + //Mark E-RAB with context setup + erab_ctx->state = ERAB_CTX_SETUP; + + //Set the GTP information + uint8_t *bit_ptr = in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].transportLayerAddress.buffer; + erab_ctx->enb_fteid.ipv4 = htonl(liblte_bits_2_value(&bit_ptr,32)); + memcpy(&erab_ctx->enb_fteid.teid, in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].gTP_TEID.buffer, 4); + erab_ctx->enb_fteid.teid = ntohl(erab_ctx->enb_fteid.teid); + + char enb_addr_str[INET_ADDRSTRLEN+1]; + const char *err = inet_ntop(AF_INET, &erab_ctx->enb_fteid.ipv4,enb_addr_str,sizeof(enb_addr_str)); + if(err == NULL) + { + m_s1ap_log->error("Error converting IP to string\n"); + } + + m_s1ap_log->info("E-RAB Context Setup. E-RAB id %d\n",erab_ctx->erab_id); + m_s1ap_log->info("E-RAB Context -- eNB TEID 0x%x, eNB Address %s\n", erab_ctx->enb_fteid.teid, enb_addr_str); + m_s1ap_log->console("E-RAB Context Setup. E-RAB id %d\n",erab_ctx->erab_id); + m_s1ap_log->console("E-RAB Context -- eNB TEID 0x%x; eNB GTP-U Address %s\n", erab_ctx->enb_fteid.teid, enb_addr_str); + + } + return true; +} + +bool +s1ap_ctx_mngmt_proc::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri, srslte::byte_buffer_t *reply_buffer, bool *reply_flag) +{ + + uint32_t mme_ue_s1ap_id = ue_rel->MME_UE_S1AP_ID.MME_UE_S1AP_ID; + m_s1ap_log->info("Received UE Context Release Request. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); + m_s1ap_log->console("Received UE Context Release Request. MME-UE S1AP Id %d\n", mme_ue_s1ap_id); + + ue_ctx_t *ue_ctx = m_s1ap->find_ue_ctx(mme_ue_s1ap_id); + if(ue_ctx == NULL) + { + m_s1ap_log->info("UE not found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); + return false; + } + + //Delete any context at the SPGW + bool active = false; + for(int i=0;ierabs_ctx[i].state != ERAB_DEACTIVATED) + { + active = true; + break; + } + } + if(active == true) + { + //There are active E-RABs, send delete session request + m_mme_gtpc->send_delete_session_request(ue_ctx); + } + m_s1ap->delete_ue_ctx(ue_ctx); + + //Delete UE context + m_s1ap_log->info("Deleted UE Context.\n"); + return true; +} + +} //namespace srsepc From 9e72fbce4363e201515b25fd1ff60b14c1e2903e Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 26 Dec 2017 15:59:57 +0000 Subject: [PATCH 146/172] Continuing to change functions to ctx_mngmnt_proc --- srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h | 3 +++ srsepc/src/mme/s1ap_ctx_mngmt_proc.cc | 13 ++++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h b/srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h index 259052b74..faa41d304 100644 --- a/srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h +++ b/srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h @@ -31,6 +31,7 @@ #include "mme/s1ap_common.h" #include "srslte/common/log_filter.h" #include "mme/mme_gtpc.h" +#include "srslte/common/buffer_pool.h" namespace srsepc{ @@ -55,11 +56,13 @@ private: virtual ~s1ap_ctx_mngmt_proc(); s1ap* m_s1ap; + s1ap_nas_transport* m_s1ap_nas_transport; srslte::log_filter *m_s1ap_log; s1ap_args_t m_s1ap_args; mme_gtpc* m_mme_gtpc; + srslte::byte_buffer_pool *m_pool; }; } //namespace srsepc diff --git a/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc index 603b80b34..e2023bc90 100644 --- a/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc +++ b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc @@ -28,6 +28,8 @@ #include "srslte/common/bcd_helpers.h" #include "mme/s1ap.h" #include "mme/s1ap_ctx_mngmt_proc.h" +#include "srslte/common/liblte_security.h" + namespace srsepc{ @@ -70,12 +72,14 @@ s1ap_ctx_mngmt_proc::init(void) m_mme_gtpc = mme_gtpc::get_instance(); m_s1ap_log = m_s1ap->m_s1ap_log; m_s1ap_args = m_s1ap->m_s1ap_args; + m_pool = srslte::byte_buffer_pool::get_instance(); + m_s1ap_nas_transport = s1ap_nas_transport::get_instance(); } bool s1ap_ctx_mngmt_proc::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp, struct srslte::gtpc_f_teid_ie sgw_ctrl_fteid) { - ue_ctx_t *ue_ctx; + int s1mme = m_s1ap->get_s1_mme(); //Prepare reply PDU LIBLTE_S1AP_S1AP_PDU_STRUCT pdu; @@ -94,13 +98,12 @@ s1ap_ctx_mngmt_proc::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, m_s1ap_log->info("Preparing to send Initial Context Setup request\n"); //Find UE Context - std::map::iterator ue_ctx_it = m_active_ues.find(mme_ue_s1ap_id); - if(ue_ctx_it == m_active_ues.end()) + ue_ctx_t *ue_ctx = m_s1ap->find_ue_ctx(mme_ue_s1ap_id); + if(ue_ctx == NULL) { m_s1ap_log->error("Could not find UE to send Setup Context Request. MME S1AP Id: %d", mme_ue_s1ap_id); return false; } - ue_ctx = ue_ctx_it->second; //Add MME and eNB S1AP Ids in_ctxt_req->MME_UE_S1AP_ID.MME_UE_S1AP_ID = ue_ctx->mme_ue_s1ap_id; @@ -184,7 +187,7 @@ s1ap_ctx_mngmt_proc::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, return false; } //Send Reply to eNB - ssize_t n_sent = sctp_send(m_s1mme,reply_buffer->msg, reply_buffer->N_bytes, &ue_ctx->enb_sri, 0); + ssize_t n_sent = sctp_send(s1mme,reply_buffer->msg, reply_buffer->N_bytes, &ue_ctx->enb_sri, 0); if(n_sent == -1) { m_s1ap_log->error("Failed to send Initial Context Setup Request\n"); From 3beb708806002f8e4e72a40d55195ef6583d8607 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 27 Dec 2017 16:21:30 +0000 Subject: [PATCH 147/172] Moved context mangement functions to s1ap_ctx_mngmnt_proc class. --- srsepc/hdr/mme/s1ap.h | 15 ++++++++------- srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h | 2 +- srsepc/src/mme/mme_gtpc.cc | 2 +- srsepc/src/mme/s1ap.cc | 9 +++++---- srsepc/src/mme/s1ap_ctx_mngmt_proc.cc | 2 +- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 93ded1b46..ba4a982eb 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -71,9 +71,9 @@ public: bool handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri); bool handle_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *msg); - bool handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri); - bool send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp, struct srslte::gtpc_f_teid_ie sgw_ctrl_fteid); - bool handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *in_ctxt_resp); + //bool handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri); + //bool send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp, struct srslte::gtpc_f_teid_ie sgw_ctrl_fteid); + //bool handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *in_ctxt_resp); void activate_eps_bearer(uint32_t mme_s1ap_id, uint8_t ebi); @@ -90,6 +90,10 @@ public: s1ap_args_t m_s1ap_args; srslte::log_filter *m_s1ap_log; + s1ap_mngmt_proc* m_s1ap_mngmt_proc; + s1ap_nas_transport* m_s1ap_nas_transport; + s1ap_ctx_mngmt_proc* m_s1ap_ctx_mngmt_proc; + private: s1ap(); virtual ~s1ap(); @@ -107,10 +111,7 @@ private: std::map > m_enb_id_to_ue_ids; uint32_t m_next_mme_ue_s1ap_id; - s1ap_mngmt_proc* m_s1ap_mngmt_proc; - s1ap_nas_transport* m_s1ap_nas_transport; - s1ap_ctx_mngmt_proc* m_s1ap_ctx_mngmt_proc; - + //FIXME the GTP-C should be moved to the MME class, the the packaging of GTP-C messages is done. mme_gtpc *m_mme_gtpc; }; diff --git a/srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h b/srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h index faa41d304..2eaca64ab 100644 --- a/srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h +++ b/srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h @@ -48,7 +48,7 @@ public: void init(void); bool send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp, struct srslte::gtpc_f_teid_ie sgw_ctrl_fteid); - bool handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *in_ctxt_resp, struct sctp_sndrcvinfo *enb_sri, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); + bool handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *in_ctxt_resp); bool handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); private: diff --git a/srsepc/src/mme/mme_gtpc.cc b/srsepc/src/mme/mme_gtpc.cc index ade0a0687..a6f09148d 100644 --- a/srsepc/src/mme/mme_gtpc.cc +++ b/srsepc/src/mme/mme_gtpc.cc @@ -160,7 +160,7 @@ mme_gtpc::handle_create_session_response(srslte::gtpc_pdu *cs_resp_pdu) sgw_ctrl_fteid.teid = cs_resp_pdu->header.teid; sgw_ctrl_fteid.ipv4 = 0; //FIXME This is not used for now. In the future it will be obtained from the socket addr_info - m_s1ap->send_initial_context_setup_request(mme_s1ap_id, cs_resp, sgw_ctrl_fteid); + m_s1ap->m_s1ap_ctx_mngmt_proc->send_initial_context_setup_request(mme_s1ap_id, cs_resp, sgw_ctrl_fteid); } diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 55b431411..e0887c44d 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -274,7 +274,8 @@ s1ap::handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, stru break; case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UECONTEXTRELEASEREQUEST: m_s1ap_log->info("Received UE Context Release Request Message.\n"); - return handle_ue_context_release_request(&msg->choice.UEContextReleaseRequest, enb_sri); + m_s1ap_ctx_mngmt_proc->handle_ue_context_release_request(&msg->choice.UEContextReleaseRequest, enb_sri, reply_buffer, &reply_flag); + break; default: m_s1ap_log->error("Unhandled intiating message: %s\n", liblte_s1ap_initiatingmessage_choice_text[msg->choice_type]); } @@ -299,14 +300,14 @@ s1ap::handle_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *msg) switch(msg->choice_type) { case LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_INITIALCONTEXTSETUPRESPONSE: m_s1ap_log->info("Received Initial Context Setup Response.\n"); - return handle_initial_context_setup_response(&msg->choice.InitialContextSetupResponse); + return m_s1ap_ctx_mngmt_proc->handle_initial_context_setup_response(&msg->choice.InitialContextSetupResponse); default: m_s1ap_log->error("Unhandled successful outcome message: %s\n", liblte_s1ap_successfuloutcome_choice_text[msg->choice_type]); } return true; } - + /* bool s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp, struct srslte::gtpc_f_teid_ie sgw_ctrl_fteid) { @@ -542,7 +543,7 @@ s1ap::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQU m_s1ap_log->info("Deleted UE Context.\n"); return true; } - + */ bool s1ap::delete_ue_ctx(ue_ctx_t *ue_ctx) { diff --git a/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc index e2023bc90..48efaee9f 100644 --- a/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc +++ b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc @@ -212,7 +212,7 @@ s1ap_ctx_mngmt_proc::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, } bool -s1ap_ctx_mngmt_proc::handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *in_ctxt_resp, struct sctp_sndrcvinfo *enb_sri, srslte::byte_buffer_t *reply_buffer, bool *reply_flag) +s1ap_ctx_mngmt_proc::handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *in_ctxt_resp) { uint32_t mme_ue_s1ap_id = in_ctxt_resp->MME_UE_S1AP_ID.MME_UE_S1AP_ID; From 57990ba60d79404db3fdd55d143aee20bcbcb6b1 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Sat, 6 Jan 2018 12:57:49 +0000 Subject: [PATCH 148/172] Added more configuration options to the EPC logs. --- srsepc/epc.conf.example | 28 ++++++++++++ srsepc/src/main.cc | 99 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 115 insertions(+), 12 deletions(-) diff --git a/srsepc/epc.conf.example b/srsepc/epc.conf.example index 861bab6a8..65f51981a 100644 --- a/srsepc/epc.conf.example +++ b/srsepc/epc.conf.example @@ -42,3 +42,31 @@ db_file = user_db.csv [spgw] gtpu_bind_addr=127.0.1.100 sgi_if_addr=172.16.0.1 + +#################################################################### +# Log configuration +# +# Log levels can be set for individual layers. "all_level" sets log +# level for all layers unless otherwise configured. +# Format: e.g. phy_level = info +# +# In the same way, packet hex dumps can be limited for each level. +# "all_hex_limit" sets the hex limit for all layers unless otherwise +# configured. +# Format: e.g. phy_hex_limit = 32 +# +# Logging layers: phy, mac, rlc, pdcp, rrc, nas, gtpu, usim, all +# Logging levels: debug, info, warning, error, none +# +# filename: File path to use for log output. Can be set to stdout +# to print logs to standard output +##################################################################### +[log] +all_level = info +all_hex_limit = 32 +filename = /tmp/epc.log + +#s1ap_level = debug +#gtpc_level = debug +#spgw_level = debug +#hss_level = debug diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index 7b6ec7025..9d604694a 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -26,6 +26,7 @@ #include #include #include +#include #include "srslte/common/bcd_helpers.h" #include "mme/mme.h" #include "hss/hss.h" @@ -43,8 +44,17 @@ sig_int_handler(int signo){ } typedef struct { + std::string s1ap_level; + int s1ap_hex_limit; + std::string gtpc_level; + int gtpc_hex_limit; + std::string spgw_level; + int spgw_hex_limit; + std::string hss_level; + int hss_hex_limit; + std::string all_level; - int hex_limit; + int all_hex_limit; std::string filename; }log_args_t; @@ -75,6 +85,7 @@ parse_args(all_args_t *args, int argc, char* argv[]) { string sgi_if_addr; string hss_db_file; string hss_auth_algo; + string log_filename; // Command line only options bpo::options_description general("General options"); @@ -98,9 +109,24 @@ parse_args(all_args_t *args, int argc, char* argv[]) { ("hss.auth_algo", bpo::value(&hss_auth_algo)->default_value("milenage"),"HSS uthentication algorithm.") ("spgw.gtpu_bind_addr", bpo::value(&spgw_bind_addr)->default_value("127.0.0.1"),"IP address of SP-GW for the S1-U connection") ("spgw.sgi_if_addr", bpo::value(&sgi_if_addr)->default_value("176.16.0.1"),"IP address of TUN interface for the SGi connection") + + ("log.s1ap_level", bpo::value(&args->log_args.s1ap_level), "MME S1AP log level") + ("log.s1ap_hex_limit", bpo::value(&args->log_args.s1ap_hex_limit), "MME S1AP log hex dump limit") + ("log.gtpc_level", bpo::value(&args->log_args.gtpc_level), "MME GTPC log level") + ("log.gtpc_hex_limit", bpo::value(&args->log_args.gtpc_hex_limit), "MME GTPC log hex dump limit") + ("log.spgw_level", bpo::value(&args->log_args.spgw_level), "SPGW log level") + ("log.spgw_hex_limit", bpo::value(&args->log_args.spgw_hex_limit), "SPGW log hex dump limit") + //("log.gtpu_level", bpo::value(&args->log.gtpu_level), "GTPU log level") + ("log.hss_level", bpo::value(&args->log_args.hss_level), "HSS log level") + ("log.hss_hex_limit", bpo::value(&args->log_args.hss_hex_limit), "HSS log hex dump limit") + //("log.gtpu_hex_limit",bpo::value(&args->log.gtpu_hex_limit), "GTPU log hex dump limit") + + ("log.all_level", bpo::value(&args->log_args.all_level)->default_value("info"), "ALL log level") + ("log.all_hex_limit", bpo::value(&args->log_args.all_hex_limit)->default_value(32), "ALL log hex dump limit") + + ("log.filename", bpo::value(&args->log_args.filename)->default_value("/tmp/epc.log"),"Log filename") ; - - + // Positional options - config file location bpo::options_description position("Positional options"); position.add_options() @@ -174,9 +200,59 @@ parse_args(all_args_t *args, int argc, char* argv[]) { args->spgw_args.sgi_if_addr = sgi_if_addr; args->hss_args.db_file = hss_db_file; args->hss_args.auth_algo = hss_auth_algo; + + // Apply all_level to any unset layers + if (vm.count("log.all_level")) { + if(!vm.count("log.s1ap_level")) { + args->log_args.s1ap_level = args->log_args.all_level; + } + if(!vm.count("log.gtpc_level")) { + args->log_args.gtpc_level = args->log_args.all_level; + } + if(!vm.count("log.spgw_level")) { + args->log_args.spgw_level = args->log_args.all_level; + } + if(!vm.count("log.hss_level")) { + args->log_args.hss_level = args->log_args.all_level; + } + } + + // Apply all_hex_limit to any unset layers + if (vm.count("log.all_hex_limit")) { + if(!vm.count("log.s1ap_hex_limit")) { + args->log_args.s1ap_hex_limit = args->log_args.all_hex_limit; + } + if(!vm.count("log.gtpc_hex_limit")) { + args->log_args.gtpc_hex_limit = args->log_args.all_hex_limit; + } + if(!vm.count("log.spgw_hex_limit")) { + args->log_args.spgw_hex_limit = args->log_args.all_hex_limit; + } + if(!vm.count("log.hss_hex_limit")) { + args->log_args.hss_hex_limit = args->log_args.all_hex_limit; + } + } return; } +srslte::LOG_LEVEL_ENUM +level(std::string l) +{ + boost::to_upper(l); + if("NONE" == l){ + return srslte::LOG_LEVEL_NONE; + }else if("ERROR" == l){ + return srslte::LOG_LEVEL_ERROR; + }else if("WARNING" == l){ + return srslte::LOG_LEVEL_WARNING; + }else if("INFO" == l){ + return srslte::LOG_LEVEL_INFO; + }else if("DEBUG" == l){ + return srslte::LOG_LEVEL_DEBUG; + }else{ + return srslte::LOG_LEVEL_NONE; + } +} int main (int argc,char * argv[] ) @@ -193,7 +269,6 @@ main (int argc,char * argv[] ) /*Init logger*/ - args.log_args.filename = std::string("/tmp/epc.log"); if (!args.log_args.filename.compare("stdout")) { logger = &logger_stdout; } else { @@ -204,23 +279,23 @@ main (int argc,char * argv[] ) srslte::log_filter s1ap_log; s1ap_log.init("S1AP",logger); - s1ap_log.set_level(srslte::LOG_LEVEL_DEBUG); - s1ap_log.set_hex_limit(32); + s1ap_log.set_level(level(args.log_args.s1ap_level)); + s1ap_log.set_hex_limit(args.log_args.s1ap_hex_limit); srslte::log_filter mme_gtpc_log; mme_gtpc_log.init("GTPC",logger); - mme_gtpc_log.set_level(srslte::LOG_LEVEL_DEBUG); - mme_gtpc_log.set_hex_limit(32); + mme_gtpc_log.set_level(level(args.log_args.gtpc_level)); + mme_gtpc_log.set_hex_limit(args.log_args.gtpc_hex_limit); srslte::log_filter hss_log; hss_log.init("HSS ",logger); - hss_log.set_level(srslte::LOG_LEVEL_DEBUG); - hss_log.set_hex_limit(32); + hss_log.set_level(level(args.log_args.hss_level)); + hss_log.set_hex_limit(args.log_args.hss_hex_limit); srslte::log_filter spgw_log; spgw_log.init("SPGW",logger); - spgw_log.set_level(srslte::LOG_LEVEL_DEBUG); - spgw_log.set_hex_limit(32); + spgw_log.set_level(level(args.log_args.spgw_level)); + spgw_log.set_hex_limit(args.log_args.spgw_hex_limit); mme *mme = mme::get_instance(); if (mme->init(&args.mme_args, &s1ap_log, &mme_gtpc_log)) { From b14c6e85f4f43e6ffea64ebb7ff78d4db15c70bf Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Sat, 6 Jan 2018 17:26:28 +0000 Subject: [PATCH 149/172] Small commit --- srsepc/src/mme/s1ap_nas_transport.cc | 222 +++++++++++++-------------- 1 file changed, 111 insertions(+), 111 deletions(-) diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 7e911fcc4..3a8425f91 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -729,6 +729,117 @@ s1ap_nas_transport::pack_esm_information_request(srslte::byte_buffer_t *reply_ms return true; } +bool +s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT *erab_ctxt, struct srslte::gtpc_pdn_address_allocation_ie *paa, srslte::byte_buffer_t *nas_buffer) { + LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT attach_accept; + LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT act_def_eps_bearer_context_req; + bzero(&act_def_eps_bearer_context_req,sizeof(LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT)); + + m_s1ap_log->info("Packing Attach Accept\n"); + + //Attach accept + attach_accept.eps_attach_result = LIBLTE_MME_EPS_ATTACH_RESULT_EPS_ONLY; + //Mandatory + //FIXME: Set t3412 from config + attach_accept.t3412.unit = LIBLTE_MME_GPRS_TIMER_UNIT_1_MINUTE; // GPRS 1 minute unit + attach_accept.t3412.value = 30; // 30 minute periodic timer + //FIXME: Set tai_list from config + attach_accept.tai_list.N_tais = 1; + attach_accept.tai_list.tai[0].mcc = 1; + attach_accept.tai_list.tai[0].mnc = 1; + attach_accept.tai_list.tai[0].tac = 7; + + //Allocate a GUTI ot the UE + attach_accept.guti_present=true; + attach_accept.guti.type_of_id = 6; //110 -> GUTI + attach_accept.guti.guti.mcc = 1; + attach_accept.guti.guti.mnc = 1; + attach_accept.guti.guti.mme_group_id = 0x0001; + attach_accept.guti.guti.mme_code = 0x1a; + attach_accept.guti.guti.m_tmsi = 0x124ae; + /* + typedef struct{ + uint32 m_tmsi; + uint16 mcc; + uint16 mnc; + uint16 mme_group_id; + uint8 mme_code; + }LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT; + typedef struct{ + LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti; + uint8 type_of_id; + uint8 imsi[15]; + uint8 imei[15]; + }LIBLTE_MME_EPS_MOBILE_ID_STRUCT;*/ + + //Make sure all unused options are set to false + attach_accept.lai_present=false; + attach_accept.ms_id_present=false; + attach_accept.emm_cause_present=false; + attach_accept.t3402_present=false; + attach_accept.t3423_present=false; + attach_accept.equivalent_plmns_present=false; + attach_accept.emerg_num_list_present=false; + attach_accept.eps_network_feature_support_present=false; + attach_accept.additional_update_result_present=false; + attach_accept.t3412_ext_present=false; + + //Set activate default eps bearer (esm_ms) + //Set pdn_addr + act_def_eps_bearer_context_req.pdn_addr.pdn_type = LIBLTE_MME_PDN_TYPE_IPV4; + memcpy(act_def_eps_bearer_context_req.pdn_addr.addr, &paa->ipv4, 4); + //Set eps bearer id + act_def_eps_bearer_context_req.eps_bearer_id = erab_ctxt->e_RAB_ID.E_RAB_ID; + printf("%d\n",act_def_eps_bearer_context_req.eps_bearer_id); + act_def_eps_bearer_context_req.transaction_id_present = false; + //set eps_qos + act_def_eps_bearer_context_req.eps_qos.qci = erab_ctxt->e_RABlevelQoSParameters.qCI.QCI; + act_def_eps_bearer_context_req.eps_qos.mbr_ul = 254; //FIXME + act_def_eps_bearer_context_req.eps_qos.mbr_dl = 254; //FIXME + act_def_eps_bearer_context_req.eps_qos.mbr_ul_ext = 250; //FIXME + act_def_eps_bearer_context_req.eps_qos.mbr_dl_ext = 250; //FIXME check + //set apn + //act_def_eps_bearer_context_req.apn + std::string apn("test123"); + act_def_eps_bearer_context_req.apn.apn = apn; //FIXME + act_def_eps_bearer_context_req.proc_transaction_id = ue_ctx->procedure_transaction_id; //FIXME + + //Set DNS server + act_def_eps_bearer_context_req.protocol_cnfg_opts_present = true; + act_def_eps_bearer_context_req.protocol_cnfg_opts.N_opts = 1; + act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].id = 0x0d; + act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].len = 4; + act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].contents[0] = 8; + act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].contents[1] = 8; + act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].contents[2] = 8; + act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].contents[3] = 8; + + uint8_t sec_hdr_type =2; + ue_ctx->security_ctxt.dl_nas_count++; + liblte_mme_pack_activate_default_eps_bearer_context_request_msg(&act_def_eps_bearer_context_req, &attach_accept.esm_msg); + liblte_mme_pack_attach_accept_msg(&attach_accept, sec_hdr_type, ue_ctx->security_ctxt.dl_nas_count, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + //Integrity protect NAS message + uint8_t mac[4]; + srslte::security_128_eia1 (&ue_ctx->security_ctxt.k_nas_int[16], + ue_ctx->security_ctxt.dl_nas_count, + 0, + SECURITY_DIRECTION_DOWNLINK, + &nas_buffer->msg[5], + nas_buffer->N_bytes - 5, + mac + ); + + memcpy(&nas_buffer->msg[1],mac,4); + m_s1ap_log->info("Packed Attach Complete\n"); + + //Add nas message to context setup request + erab_ctxt->nAS_PDU_present = true; + memcpy(erab_ctxt->nAS_PDU.buffer, nas_buffer->msg, nas_buffer->N_bytes); + erab_ctxt->nAS_PDU.n_octets = nas_buffer->N_bytes; + + return true; +} + /*Helper functions*/ @@ -857,115 +968,4 @@ s1ap_nas_transport::log_unhandled_initial_ue_message_ies(LIBLTE_S1AP_MESSAGE_INI } -bool -s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT *erab_ctxt, struct srslte::gtpc_pdn_address_allocation_ie *paa, srslte::byte_buffer_t *nas_buffer) { - LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT attach_accept; - LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT act_def_eps_bearer_context_req; - bzero(&act_def_eps_bearer_context_req,sizeof(LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT)); - - m_s1ap_log->info("Packing Attach Accept\n"); - - //Attach accept - attach_accept.eps_attach_result = LIBLTE_MME_EPS_ATTACH_RESULT_EPS_ONLY; - //Mandatory - //FIXME: Set t3412 from config - attach_accept.t3412.unit = LIBLTE_MME_GPRS_TIMER_UNIT_1_MINUTE; // GPRS 1 minute unit - attach_accept.t3412.value = 30; // 30 minute periodic timer - //FIXME: Set tai_list from config - attach_accept.tai_list.N_tais = 1; - attach_accept.tai_list.tai[0].mcc = 1; - attach_accept.tai_list.tai[0].mnc = 1; - attach_accept.tai_list.tai[0].tac = 7; - - //Allocate a GUTI ot the UE - attach_accept.guti_present=true; - attach_accept.guti.type_of_id = 6; //110 -> GUTI - attach_accept.guti.guti.mcc = 1; - attach_accept.guti.guti.mnc = 1; - attach_accept.guti.guti.mme_group_id = 0x0001; - attach_accept.guti.guti.mme_code = 0x1a; - attach_accept.guti.guti.m_tmsi = 0x124ae; - /* - typedef struct{ - uint32 m_tmsi; - uint16 mcc; - uint16 mnc; - uint16 mme_group_id; - uint8 mme_code; - }LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT; - typedef struct{ - LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti; - uint8 type_of_id; - uint8 imsi[15]; - uint8 imei[15]; - }LIBLTE_MME_EPS_MOBILE_ID_STRUCT;*/ - - //Make sure all unused options are set to false - attach_accept.lai_present=false; - attach_accept.ms_id_present=false; - attach_accept.emm_cause_present=false; - attach_accept.t3402_present=false; - attach_accept.t3423_present=false; - attach_accept.equivalent_plmns_present=false; - attach_accept.emerg_num_list_present=false; - attach_accept.eps_network_feature_support_present=false; - attach_accept.additional_update_result_present=false; - attach_accept.t3412_ext_present=false; - - //Set activate default eps bearer (esm_ms) - //Set pdn_addr - act_def_eps_bearer_context_req.pdn_addr.pdn_type = LIBLTE_MME_PDN_TYPE_IPV4; - memcpy(act_def_eps_bearer_context_req.pdn_addr.addr, &paa->ipv4, 4); - //Set eps bearer id - act_def_eps_bearer_context_req.eps_bearer_id = erab_ctxt->e_RAB_ID.E_RAB_ID; - printf("%d\n",act_def_eps_bearer_context_req.eps_bearer_id); - act_def_eps_bearer_context_req.transaction_id_present = false; - //set eps_qos - act_def_eps_bearer_context_req.eps_qos.qci = erab_ctxt->e_RABlevelQoSParameters.qCI.QCI; - act_def_eps_bearer_context_req.eps_qos.mbr_ul = 254; //FIXME - act_def_eps_bearer_context_req.eps_qos.mbr_dl = 254; //FIXME - act_def_eps_bearer_context_req.eps_qos.mbr_ul_ext = 250; //FIXME - act_def_eps_bearer_context_req.eps_qos.mbr_dl_ext = 250; //FIXME check - //set apn - //act_def_eps_bearer_context_req.apn - std::string apn("test123"); - act_def_eps_bearer_context_req.apn.apn = apn; //FIXME - act_def_eps_bearer_context_req.proc_transaction_id = ue_ctx->procedure_transaction_id; //FIXME - - //Set DNS server - act_def_eps_bearer_context_req.protocol_cnfg_opts_present = true; - act_def_eps_bearer_context_req.protocol_cnfg_opts.N_opts = 1; - act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].id = 0x0d; - act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].len = 4; - act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].contents[0] = 8; - act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].contents[1] = 8; - act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].contents[2] = 8; - act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].contents[3] = 8; - - uint8_t sec_hdr_type =2; - ue_ctx->security_ctxt.dl_nas_count++; - liblte_mme_pack_activate_default_eps_bearer_context_request_msg(&act_def_eps_bearer_context_req, &attach_accept.esm_msg); - liblte_mme_pack_attach_accept_msg(&attach_accept, sec_hdr_type, ue_ctx->security_ctxt.dl_nas_count, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); - //Integrity protect NAS message - uint8_t mac[4]; - srslte::security_128_eia1 (&ue_ctx->security_ctxt.k_nas_int[16], - ue_ctx->security_ctxt.dl_nas_count, - 0, - SECURITY_DIRECTION_DOWNLINK, - &nas_buffer->msg[5], - nas_buffer->N_bytes - 5, - mac - ); - - memcpy(&nas_buffer->msg[1],mac,4); - m_s1ap_log->info("Packed Attach Complete\n"); - - //Add nas message to context setup request - erab_ctxt->nAS_PDU_present = true; - memcpy(erab_ctxt->nAS_PDU.buffer, nas_buffer->msg, nas_buffer->N_bytes); - erab_ctxt->nAS_PDU.n_octets = nas_buffer->N_bytes; - - return true; -} - } //namespace srsepc From 84e0723c3d48b78f0c279a89848852dadfefa22d Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 10 Jan 2018 11:35:08 +0000 Subject: [PATCH 150/172] Starting to add the mechanisms to perform GUTI attach. --- srsepc/hdr/mme/s1ap.h | 10 +- srsepc/src/mme/s1ap.cc | 244 +-------------------------- srsepc/src/mme/s1ap_nas_transport.cc | 42 +++-- 3 files changed, 42 insertions(+), 254 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index ba4a982eb..509a887ee 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -71,10 +71,6 @@ public: bool handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri); bool handle_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *msg); - //bool handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri); - //bool send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp, struct srslte::gtpc_f_teid_ie sgw_ctrl_fteid); - //bool handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *in_ctxt_resp); - void activate_eps_bearer(uint32_t mme_s1ap_id, uint8_t ebi); void print_enb_ctx_info(const std::string &prefix, const enb_ctx_t &enb_ctx); @@ -87,6 +83,8 @@ public: void add_new_ue_ctx(const ue_ctx_t &ue_ctx); bool delete_ue_ctx(ue_ctx_t *ue_ctx); + uint32_t allocate_m_tmsi(); + s1ap_args_t m_s1ap_args; srslte::log_filter *m_s1ap_log; @@ -94,6 +92,8 @@ public: s1ap_nas_transport* m_s1ap_nas_transport; s1ap_ctx_mngmt_proc* m_s1ap_ctx_mngmt_proc; + std::map m_tmsi_to_s1ap_id; + private: s1ap(); virtual ~s1ap(); @@ -110,8 +110,8 @@ private: std::map m_active_ues; std::map > m_enb_id_to_ue_ids; uint32_t m_next_mme_ue_s1ap_id; + uint32_t m_next_m_tmsi; - //FIXME the GTP-C should be moved to the MME class, the the packaging of GTP-C messages is done. mme_gtpc *m_mme_gtpc; }; diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index e0887c44d..03eaadd35 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -73,7 +73,7 @@ s1ap::init(s1ap_args_t s1ap_args, srslte::log_filter *s1ap_log) m_s1ap_args = s1ap_args; srslte::s1ap_mccmnc_to_plmn(s1ap_args.mcc, s1ap_args.mnc, &m_plmn); - + m_next_m_tmsi = rand(); //Init log m_s1ap_log = s1ap_log; @@ -307,243 +307,7 @@ s1ap::handle_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *msg) return true; } - /* -bool -s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp, struct srslte::gtpc_f_teid_ie sgw_ctrl_fteid) -{ - ue_ctx_t *ue_ctx; - //Prepare reply PDU - LIBLTE_S1AP_S1AP_PDU_STRUCT pdu; - bzero(&pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); - pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE; - - LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *init = &pdu.choice.initiatingMessage; - init->procedureCode = LIBLTE_S1AP_PROC_ID_INITIALCONTEXTSETUP; - init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_INITIALCONTEXTSETUPREQUEST; - - LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT *in_ctxt_req = &init->choice.InitialContextSetupRequest; - - LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT *erab_ctxt = &in_ctxt_req->E_RABToBeSetupListCtxtSUReq.buffer[0]; //FIXME support more than one erab - srslte::byte_buffer_t *reply_buffer = m_pool->allocate(); - - m_s1ap_log->info("Preparing to send Initial Context Setup request\n"); - - //Find UE Context - std::map::iterator ue_ctx_it = m_active_ues.find(mme_ue_s1ap_id); - if(ue_ctx_it == m_active_ues.end()) - { - m_s1ap_log->error("Could not find UE to send Setup Context Request. MME S1AP Id: %d", mme_ue_s1ap_id); - return false; - } - ue_ctx = ue_ctx_it->second; - - //Add MME and eNB S1AP Ids - in_ctxt_req->MME_UE_S1AP_ID.MME_UE_S1AP_ID = ue_ctx->mme_ue_s1ap_id; - in_ctxt_req->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ue_ctx->enb_ue_s1ap_id; - - //Set UE-AMBR - in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL.BitRate=1000000000;//2^32-1 - in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL.BitRate=1000000000;//FIXME Get UE-AMBR from HSS - - //Setup eRAB context - in_ctxt_req->E_RABToBeSetupListCtxtSUReq.len = 1; - erab_ctxt->e_RAB_ID.E_RAB_ID = cs_resp->eps_bearer_context_created.ebi; - //Setup E-RAB QoS parameters - erab_ctxt->e_RABlevelQoSParameters.qCI.QCI = 9; - erab_ctxt->e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel.PriorityLevel = 15 ;//Lowest - erab_ctxt->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability = LIBLTE_S1AP_PRE_EMPTIONCAPABILITY_SHALL_NOT_TRIGGER_PRE_EMPTION; - erab_ctxt->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability = LIBLTE_S1AP_PRE_EMPTIONVULNERABILITY_PRE_EMPTABLE; - - erab_ctxt->e_RABlevelQoSParameters.gbrQosInformation_present=false; - - //Set E-RAB S-GW F-TEID - if (cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid_present == false){ - m_s1ap_log->error("Did not receive S1-U TEID in create session response\n"); - return false; - } - erab_ctxt->transportLayerAddress.n_bits = 32; //IPv4 - uint32_t sgw_s1u_ip = htonl(cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.ipv4); - //uint32_t sgw_s1u_ip = cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.ipv4; - uint8_t *tmp_ptr = erab_ctxt->transportLayerAddress.buffer; - liblte_value_2_bits(sgw_s1u_ip, &tmp_ptr, 32);//FIXME consider ipv6 - - uint32_t tmp_teid = cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.teid; - memcpy(erab_ctxt->gTP_TEID.buffer, &tmp_teid, sizeof(uint32_t)); - - //Set UE security capabilities and k_enb - bzero(in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer,sizeof(uint8_t)*16); - bzero(in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer,sizeof(uint8_t)*16); - for(int i = 0; i<3; i++) - { - if(ue_ctx->ue_network_cap.eea[i+1] == true) - { - in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer[i] = 1; //EEA supported - } - else - { - in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer[i] = 0; //EEA not supported - } - if(ue_ctx->ue_network_cap.eia[i+1] == true) - { - in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[i] = 1; //EEA supported - } - else - { - in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[i] = 0; //EEA not supported - } - // in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[0] = 1; //EIA1 - } - uint8_t key_enb[32]; - liblte_security_generate_k_enb(ue_ctx->security_ctxt.k_asme, ue_ctx->security_ctxt.ul_nas_count, key_enb); - liblte_unpack(key_enb, 32, in_ctxt_req->SecurityKey.buffer); - m_s1ap_log->info("Generating KeNB with UL NAS COUNT: %d\n",ue_ctx->security_ctxt.ul_nas_count); - //Set Attach accepted and activat default bearer NAS messages - if(cs_resp->paa_present != true) - { - m_s1ap_log->error("PAA not present\n"); - return false; - } - if(cs_resp->paa.pdn_type != srslte::GTPC_PDN_TYPE_IPV4) - { - m_s1ap_log->error("IPv6 not supported yet\n"); - return false; - } - srslte::byte_buffer_t *nas_buffer = m_pool->allocate(); - m_s1ap_nas_transport->pack_attach_accept(ue_ctx, erab_ctxt, &cs_resp->paa, nas_buffer); - - - LIBLTE_ERROR_ENUM err = liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)reply_buffer); - if(err != LIBLTE_SUCCESS) - { - m_s1ap_log->error("Could not pack Initial Context Setup Request Message\n"); - return false; - } - //Send Reply to eNB - ssize_t n_sent = sctp_send(m_s1mme,reply_buffer->msg, reply_buffer->N_bytes, &ue_ctx->enb_sri, 0); - if(n_sent == -1) - { - m_s1ap_log->error("Failed to send Initial Context Setup Request\n"); - return false; - } - - //Change E-RAB state to Context Setup Requested and save S-GW control F-TEID - ue_ctx->erabs_ctx[erab_ctxt->e_RAB_ID.E_RAB_ID].state = ERAB_CTX_REQUESTED; - ue_ctx->erabs_ctx[erab_ctxt->e_RAB_ID.E_RAB_ID].sgw_ctrl_fteid.teid = sgw_ctrl_fteid.teid; - ue_ctx->erabs_ctx[erab_ctxt->e_RAB_ID.E_RAB_ID].sgw_ctrl_fteid.ipv4 = sgw_ctrl_fteid.ipv4; - - struct in_addr addr; - addr.s_addr = sgw_s1u_ip; - m_s1ap_log->info("Sent Intial Context Setup Request. E-RAB id %d \n",erab_ctxt->e_RAB_ID.E_RAB_ID); - m_s1ap_log->info("Initial Context -- S1-U TEID 0x%x. IP %s \n", tmp_teid,inet_ntoa(addr)); - m_s1ap_log->console("Sent Intial Context Setup Request, E-RAB id %d\n",erab_ctxt->e_RAB_ID.E_RAB_ID); - m_s1ap_log->console("Initial Context -- S1-U TEID 0x%x. IP %s \n", tmp_teid,inet_ntoa(addr)); - - m_pool->deallocate(reply_buffer); - m_pool->deallocate(nas_buffer); - return true; -} - - -bool -s1ap::handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *in_ctxt_resp) -{ - - uint32_t mme_ue_s1ap_id = in_ctxt_resp->MME_UE_S1AP_ID.MME_UE_S1AP_ID; - std::map::iterator ue_ctx_it = m_active_ues.find(mme_ue_s1ap_id); - if (ue_ctx_it == m_active_ues.end()) - { - m_s1ap_log->error("Could not find UE's context in active UE's map\n"); - return false; - } - for(uint32_t i=0; iE_RABSetupListCtxtSURes.len;i++) - { - uint8_t erab_id = in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].e_RAB_ID.E_RAB_ID; - erab_ctx_t *erab_ctx = &ue_ctx_it->second->erabs_ctx[erab_id]; - if (erab_ctx->state != ERAB_CTX_REQUESTED) - { - m_s1ap_log->error("E-RAB requested was not active %d\n",erab_id); - return false; - } - //Mark E-RAB with context setup - erab_ctx->state = ERAB_CTX_SETUP; - - //Set the GTP information - uint8_t *bit_ptr = in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].transportLayerAddress.buffer; - erab_ctx->enb_fteid.ipv4 = htonl(liblte_bits_2_value(&bit_ptr,32)); - memcpy(&erab_ctx->enb_fteid.teid, in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].gTP_TEID.buffer, 4); - erab_ctx->enb_fteid.teid = ntohl(erab_ctx->enb_fteid.teid); - - char enb_addr_str[INET_ADDRSTRLEN+1]; - const char *err = inet_ntop(AF_INET, &erab_ctx->enb_fteid.ipv4,enb_addr_str,sizeof(enb_addr_str)); - if(err == NULL) - { - m_s1ap_log->error("Error converting IP to string\n"); - } - - m_s1ap_log->info("E-RAB Context Setup. E-RAB id %d\n",erab_ctx->erab_id); - m_s1ap_log->info("E-RAB Context -- eNB TEID 0x%x, eNB Address %s\n", erab_ctx->enb_fteid.teid, enb_addr_str); - m_s1ap_log->console("E-RAB Context Setup. E-RAB id %d\n",erab_ctx->erab_id); - m_s1ap_log->console("E-RAB Context -- eNB TEID 0x%x; eNB GTP-U Address %s\n", erab_ctx->enb_fteid.teid, enb_addr_str); - - } - return true; -} - -bool -s1ap::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri) -{ - - uint32_t mme_ue_s1ap_id = ue_rel->MME_UE_S1AP_ID.MME_UE_S1AP_ID; - m_s1ap_log->info("Received UE Context Release Request. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); - m_s1ap_log->console("Received UE Context Release Request. MME-UE S1AP Id %d\n", mme_ue_s1ap_id); - - std::map::iterator ue_ctx = m_active_ues.find(mme_ue_s1ap_id); - if(ue_ctx == m_active_ues.end() ) - { - m_s1ap_log->info("UE not found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); - return false; - } - - //Delete UE within eNB UE set - std::map::iterator it = m_sctp_to_enb_id.find(enb_sri->sinfo_assoc_id); - if(it == m_sctp_to_enb_id.end() ) - { - m_s1ap_log->error("Could not find eNB for this request.\n"); - return false; - } - uint16_t enb_id = it->second; - std::map >::iterator ue_set = m_enb_id_to_ue_ids.find(enb_id); - if(ue_set == m_enb_id_to_ue_ids.end()) - { - m_s1ap_log->error("Could not find the eNB's UEs.\n"); - return false; - } - ue_set->second.erase(mme_ue_s1ap_id); - - //Delete any context at the SPGW - bool active = false; - for(int i=0;isecond->erabs_ctx[i].state != ERAB_DEACTIVATED) - { - active = true; - break; - } - } - if(active == true) - { - //There are active E-RABs, send delete session request - m_mme_gtpc->send_delete_session_request(ue_ctx->second); - } - - //Delete UE context - delete ue_ctx->second; - m_active_ues.erase(ue_ctx); - m_s1ap_log->info("Deleted UE Context.\n"); - return true; -} - */ bool s1ap::delete_ue_ctx(ue_ctx_t *ue_ctx) { @@ -668,6 +432,12 @@ s1ap::activate_eps_bearer(uint32_t mme_s1ap_id, uint8_t ebi) return; } +uint32_t +s1ap::allocate_m_tmsi() +{ + return m_next_m_tmsi++; +} + void s1ap::print_enb_ctx_info(const std::string &prefix, const enb_ctx_t &enb_ctx) { diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 3a8425f91..6746b7e00 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -81,7 +81,7 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT attach_req; LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT pdn_con_req; - uint64_t imsi; + uint64_t imsi = 0; uint8_t k_asme[32]; uint8_t autn[16]; uint8_t rand[6]; @@ -106,13 +106,31 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA return false; } - //Get IMSI - imsi = 0; - for(int i=0;i<=14;i++){ - imsi += attach_req.eps_mobile_id.imsi[i]*std::pow(10,14-i); + //Get Mobile ID + if(attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI) + { + //IMSI style attach + imsi = 0; + for(int i=0;i<=14;i++){ + imsi += attach_req.eps_mobile_id.imsi[i]*std::pow(10,14-i); + } + } + else if(attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI) + { + //GUTI style attach + uint32_t m_tmsi = attach_req.eps_mobile_id.guti.m_tmsi; + std::map::iterator it = m_s1ap->m_tmsi_to_s1ap_id.find(m_tmsi); + if(it == m_s1ap->m_tmsi_to_s1ap_id.end()) + { + //FIXME Send Id request + m_s1ap_log->info("Could not find M-TMSI in attach request\n"); + return false; + } + ue_ctx_t *tmp = m_s1ap->find_ue_ctx(it->second); + imsi = tmp->imsi; } m_s1ap_log->console("Attach request from IMSI: %015lu\n", imsi); - m_s1ap_log->info("Attach request from IMSI: %015lu\n", imsi); + m_s1ap_log->info("Attach request from IMSI: %015lu\n", imsi); //Get UE network capabilities memcpy(&ue_ctx.ue_network_cap, &attach_req.ue_network_cap, sizeof(LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT)); @@ -745,18 +763,18 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE attach_accept.t3412.value = 30; // 30 minute periodic timer //FIXME: Set tai_list from config attach_accept.tai_list.N_tais = 1; - attach_accept.tai_list.tai[0].mcc = 1; - attach_accept.tai_list.tai[0].mnc = 1; - attach_accept.tai_list.tai[0].tac = 7; + attach_accept.tai_list.tai[0].mcc = m_s1ap->m_s1ap_args.mcc; + attach_accept.tai_list.tai[0].mnc = m_s1ap->m_s1ap_args.mnc; + attach_accept.tai_list.tai[0].tac = m_s1ap->m_s1ap_args.tac; //Allocate a GUTI ot the UE attach_accept.guti_present=true; attach_accept.guti.type_of_id = 6; //110 -> GUTI - attach_accept.guti.guti.mcc = 1; - attach_accept.guti.guti.mnc = 1; + attach_accept.guti.guti.mcc = m_s1ap->m_s1ap_args.mcc; + attach_accept.guti.guti.mnc = m_s1ap->m_s1ap_args.mnc; attach_accept.guti.guti.mme_group_id = 0x0001; attach_accept.guti.guti.mme_code = 0x1a; - attach_accept.guti.guti.m_tmsi = 0x124ae; + attach_accept.guti.guti.m_tmsi = m_s1ap->allocate_m_tmsi(); /* typedef struct{ uint32 m_tmsi; From 45effcca0866b1a864fd8ee9ce3770b99680d640 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 10 Jan 2018 17:04:36 +0000 Subject: [PATCH 151/172] Starting to add GUTI attach support. --- srsepc/epc.conf.example | 8 ++++---- srsepc/hdr/mme/s1ap.h | 2 +- srsepc/src/mme/s1ap.cc | 6 ++++-- srsepc/src/mme/s1ap_ctx_mngmt_proc.cc | 6 +++--- srsepc/src/mme/s1ap_nas_transport.cc | 16 ++++++++++++---- 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/srsepc/epc.conf.example b/srsepc/epc.conf.example index 65f51981a..bce4085ac 100644 --- a/srsepc/epc.conf.example +++ b/srsepc/epc.conf.example @@ -48,21 +48,21 @@ sgi_if_addr=172.16.0.1 # # Log levels can be set for individual layers. "all_level" sets log # level for all layers unless otherwise configured. -# Format: e.g. phy_level = info +# Format: e.g. s1ap_level = info # # In the same way, packet hex dumps can be limited for each level. # "all_hex_limit" sets the hex limit for all layers unless otherwise # configured. -# Format: e.g. phy_hex_limit = 32 +# Format: e.g. s1ap_hex_limit = 32 # -# Logging layers: phy, mac, rlc, pdcp, rrc, nas, gtpu, usim, all +# Logging layers: s1ap, gtpc, spgw, hss, all # Logging levels: debug, info, warning, error, none # # filename: File path to use for log output. Can be set to stdout # to print logs to standard output ##################################################################### [log] -all_level = info +all_level = debug all_hex_limit = 32 filename = /tmp/epc.log diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 509a887ee..fc4dd3d49 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -83,7 +83,7 @@ public: void add_new_ue_ctx(const ue_ctx_t &ue_ctx); bool delete_ue_ctx(ue_ctx_t *ue_ctx); - uint32_t allocate_m_tmsi(); + uint32_t allocate_m_tmsi(uint32_t mme_ue_s1ap_id); s1ap_args_t m_s1ap_args; srslte::log_filter *m_s1ap_log; diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 03eaadd35..b9e303674 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -433,9 +433,11 @@ s1ap::activate_eps_bearer(uint32_t mme_s1ap_id, uint8_t ebi) } uint32_t -s1ap::allocate_m_tmsi() +s1ap::allocate_m_tmsi(uint32_t mme_ue_s1ap_id) { - return m_next_m_tmsi++; + uint32_t m_tmsi = m_next_m_tmsi++; + m_tmsi_to_s1ap_id.insert(std::pair(m_tmsi,mme_ue_s1ap_id)); + return m_tmsi; } void diff --git a/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc index 48efaee9f..70d3e7380 100644 --- a/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc +++ b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc @@ -280,7 +280,7 @@ s1ap_ctx_mngmt_proc::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECON if(ue_ctx->erabs_ctx[i].state != ERAB_DEACTIVATED) { active = true; - break; + ue_ctx->erabs_ctx[i].state = ERAB_DEACTIVATED; } } if(active == true) @@ -288,10 +288,10 @@ s1ap_ctx_mngmt_proc::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECON //There are active E-RABs, send delete session request m_mme_gtpc->send_delete_session_request(ue_ctx); } - m_s1ap->delete_ue_ctx(ue_ctx); + //m_s1ap->delete_ue_ctx(ue_ctx); //Delete UE context - m_s1ap_log->info("Deleted UE Context.\n"); + m_s1ap_log->info("Deleted UE S1-U Context.\n"); return true; } diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 6746b7e00..990ee83d0 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -106,7 +106,7 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA return false; } - //Get Mobile ID + if(attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI) { //IMSI style attach @@ -114,20 +114,27 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA for(int i=0;i<=14;i++){ imsi += attach_req.eps_mobile_id.imsi[i]*std::pow(10,14-i); } + } else if(attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI) { //GUTI style attach + m_s1ap_log->console("Received GUTI-style attach request\n"); uint32_t m_tmsi = attach_req.eps_mobile_id.guti.m_tmsi; std::map::iterator it = m_s1ap->m_tmsi_to_s1ap_id.find(m_tmsi); if(it == m_s1ap->m_tmsi_to_s1ap_id.end()) { //FIXME Send Id request - m_s1ap_log->info("Could not find M-TMSI in attach request\n"); + m_s1ap_log->console("Could not find M-TMSI in attach request\n"); return false; } + m_s1ap_log->console("Found M-TMSI: %d\n",m_tmsi); ue_ctx_t *tmp = m_s1ap->find_ue_ctx(it->second); - imsi = tmp->imsi; + if(tmp!=NULL) + { + m_s1ap_log->console("Found UE context. IMSI: %015lu\n",tmp->imsi); + imsi = tmp->imsi; + } } m_s1ap_log->console("Attach request from IMSI: %015lu\n", imsi); m_s1ap_log->info("Attach request from IMSI: %015lu\n", imsi); @@ -774,7 +781,8 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE attach_accept.guti.guti.mnc = m_s1ap->m_s1ap_args.mnc; attach_accept.guti.guti.mme_group_id = 0x0001; attach_accept.guti.guti.mme_code = 0x1a; - attach_accept.guti.guti.m_tmsi = m_s1ap->allocate_m_tmsi(); + attach_accept.guti.guti.m_tmsi = m_s1ap->allocate_m_tmsi(ue_ctx->mme_ue_s1ap_id); + /* typedef struct{ uint32 m_tmsi; From 6d4f773fba2fedc695decc50ca9028c0df3e5172 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 10 Jan 2018 18:39:04 +0000 Subject: [PATCH 152/172] Added debug print --- srsepc/src/mme/s1ap_nas_transport.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 990ee83d0..9c9eceff9 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -682,7 +682,7 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, m_s1ap_log->console("Error packing Athentication Request\n"); return false; } - + m_s1ap_log->debug_hex(reply_msg->msg, reply_msg->N_bytes, "Security Mode Command: "); m_pool->deallocate(nas_buffer); return true; } From b09ae059c16020f924bc41be0866e0b179e3061b Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 12 Jan 2018 15:11:00 +0000 Subject: [PATCH 153/172] Small commit to avoid duplication of UE ctxt in GUTI attach. --- srsepc/src/mme/s1ap_nas_transport.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 9c9eceff9..394241cb8 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -177,8 +177,12 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA ue_ctx.erabs_ctx[i].state = ERAB_DEACTIVATED; ue_ctx.erabs_ctx[i].erab_id = i; } - m_s1ap->add_new_ue_ctx(ue_ctx); + if(attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI) + { + //IMSI attach requeires new UE ctxt + m_s1ap->add_new_ue_ctx(ue_ctx); + } //Pack NAS Authentication Request in Downlink NAS Transport msg pack_authentication_request(reply_buffer, ue_ctx.enb_ue_s1ap_id, ue_ctx.mme_ue_s1ap_id, autn, rand); From 4634d13a3b8b976b0a94180deb9cc8e60dd3df6c Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 12 Jan 2018 15:53:47 +0000 Subject: [PATCH 154/172] Reverted changes in UE ctxt release request to avoid segfault. --- srsepc/src/mme/s1ap_ctx_mngmt_proc.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc index 70d3e7380..185a6f8dd 100644 --- a/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc +++ b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc @@ -280,7 +280,8 @@ s1ap_ctx_mngmt_proc::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECON if(ue_ctx->erabs_ctx[i].state != ERAB_DEACTIVATED) { active = true; - ue_ctx->erabs_ctx[i].state = ERAB_DEACTIVATED; + //ue_ctx->erabs_ctx[i].state = ERAB_DEACTIVATED; + break; } } if(active == true) @@ -288,10 +289,10 @@ s1ap_ctx_mngmt_proc::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECON //There are active E-RABs, send delete session request m_mme_gtpc->send_delete_session_request(ue_ctx); } - //m_s1ap->delete_ue_ctx(ue_ctx); + m_s1ap->delete_ue_ctx(ue_ctx); //Delete UE context - m_s1ap_log->info("Deleted UE S1-U Context.\n"); + m_s1ap_log->info("Deleted UE Context.\n"); return true; } From 3984e1d9db5a32dc229e7a09de029244026885da Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Sun, 14 Jan 2018 15:40:41 +0000 Subject: [PATCH 155/172] Added NAS identity request/response. --- srsepc/hdr/mme/s1ap_nas_transport.h | 2 + srsepc/src/mme/s1ap_nas_transport.cc | 158 ++++++++++++++++++++++----- 2 files changed, 131 insertions(+), 29 deletions(-) diff --git a/srsepc/hdr/mme/s1ap_nas_transport.h b/srsepc/hdr/mme/s1ap_nas_transport.h index fd30d2630..ae8da16b3 100644 --- a/srsepc/hdr/mme/s1ap_nas_transport.h +++ b/srsepc/hdr/mme/s1ap_nas_transport.h @@ -51,6 +51,7 @@ public: bool handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); bool handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); bool handle_esm_information_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag); + bool handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag); bool unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req, LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req); @@ -62,6 +63,7 @@ public: bool pack_esm_information_request(srslte::byte_buffer_t *reply_msg, ue_ctx_t *ue_ctx); bool pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT *erab_ctxt, struct srslte::gtpc_pdn_address_allocation_ie *paa, srslte::byte_buffer_t *nas_buffer); + bool pack_identity_request(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id); void log_unhandled_attach_request_ies(const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req); void log_unhandled_pdn_con_request_ies(const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req); diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 394241cb8..52744119f 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -106,7 +106,35 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA return false; } + //Create basic UE Ctx + ue_ctx.imsi = 0; + ue_ctx.mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id(); + //Get UE network capabilities + memcpy(&ue_ctx.ue_network_cap, &attach_req.ue_network_cap, sizeof(LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT)); + ue_ctx.ms_network_cap_present = attach_req.ms_network_cap_present; + if(attach_req.ms_network_cap_present) + { + memcpy(&ue_ctx.ms_network_cap, &attach_req.ms_network_cap, sizeof(LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT)); + } + uint8_t eps_bearer_id = pdn_con_req.eps_bearer_id; //TODO: Unused + ue_ctx.procedure_transaction_id = pdn_con_req.proc_transaction_id; + //Save whether ESM information transfer is necessary + ue_ctx.eit = pdn_con_req.esm_info_transfer_flag_present; + m_s1ap_log->console("EPS Bearer id: %d\n", eps_bearer_id); + //Initialize NAS count + ue_ctx.security_ctxt.ul_nas_count = 0; + ue_ctx.security_ctxt.dl_nas_count = 0; + //Add eNB info to UE ctxt + memcpy(&ue_ctx.enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); + //Initialize E-RABs + for(uint i = 0 ; i< MAX_ERABS_PER_UE; i++) + { + ue_ctx.erabs_ctx[i].state = ERAB_DEACTIVATED; + ue_ctx.erabs_ctx[i].erab_id = i; + } + + //Get UE Identity if(attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI) { //IMSI style attach @@ -125,8 +153,12 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA if(it == m_s1ap->m_tmsi_to_s1ap_id.end()) { //FIXME Send Id request - m_s1ap_log->console("Could not find M-TMSI in attach request\n"); - return false; + m_s1ap_log->console("Could not find M-TMSI in attach request. Sending ID request\n"); + m_s1ap_log->info("Could not find M-TMSI in attach request. Sending Id Request\n"); + m_s1ap->add_new_ue_ctx(ue_ctx); + pack_identity_request(reply_buffer, ue_ctx.mme_ue_s1ap_id, ue_ctx.enb_ue_s1ap_id); + *reply_flag = true; + return true; } m_s1ap_log->console("Found M-TMSI: %d\n",m_tmsi); ue_ctx_t *tmp = m_s1ap->find_ue_ctx(it->second); @@ -139,27 +171,7 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA m_s1ap_log->console("Attach request from IMSI: %015lu\n", imsi); m_s1ap_log->info("Attach request from IMSI: %015lu\n", imsi); - //Get UE network capabilities - memcpy(&ue_ctx.ue_network_cap, &attach_req.ue_network_cap, sizeof(LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT)); - ue_ctx.ms_network_cap_present = attach_req.ms_network_cap_present; - if(attach_req.ms_network_cap_present) - { - memcpy(&ue_ctx.ms_network_cap, &attach_req.ms_network_cap, sizeof(LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT)); - } - //FIXME use this info - uint8_t eps_bearer_id = pdn_con_req.eps_bearer_id; //TODO: Unused - ue_ctx.procedure_transaction_id = pdn_con_req.proc_transaction_id; - - //Save whether ESM information transfer is necessary - ue_ctx.eit = pdn_con_req.esm_info_transfer_flag_present; - m_s1ap_log->console("EPS Bearer id: %d\n", eps_bearer_id); - - //Initialize NAS count - ue_ctx.security_ctxt.ul_nas_count = 0; - ue_ctx.security_ctxt.dl_nas_count = 0; - //Add eNB info to UE ctxt - memcpy(&ue_ctx.enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); - + //Get Authentication Vectors from HSS if(!m_hss->gen_auth_info_answer(imsi, ue_ctx.security_ctxt.k_asme, autn, rand, ue_ctx.security_ctxt.xres)) { @@ -172,12 +184,6 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA ue_ctx.imsi = imsi; ue_ctx.mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id(); - for(uint i = 0 ; i< MAX_ERABS_PER_UE; i++) - { - ue_ctx.erabs_ctx[i].state = ERAB_DEACTIVATED; - ue_ctx.erabs_ctx[i].erab_id = i; - } - if(attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI) { //IMSI attach requeires new UE ctxt @@ -244,6 +250,11 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA handle_esm_information_response(nas_msg, ue_ctx, reply_buffer, reply_flag); ue_ctx->security_ctxt.ul_nas_count++; return true; + case LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE: + m_s1ap_log->info("UL NAS: Received ID Response\n"); + handle_identity_response(nas_msg, ue_ctx, reply_buffer, reply_flag); + //ue_ctx->security_ctxt.ul_nas_count++; + return true; default: m_s1ap_log->warning("Unhandled NAS message 0x%x\n", msg_type ); m_s1ap_log->console("Unhandled NAS message 0x%x\n", msg_type ); @@ -407,7 +418,47 @@ s1ap_nas_transport::handle_esm_information_response(srslte::byte_buffer_t *nas_m return true; } +bool +s1ap_nas_transport::handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag) +{ + uint8_t autn[16]; + uint8_t rand[6]; + uint8_t xres[8]; + LIBLTE_MME_ID_RESPONSE_MSG_STRUCT id_resp; + LIBLTE_ERROR_ENUM err = liblte_mme_unpack_identity_response_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &id_resp); + if(err != LIBLTE_SUCCESS){ + m_s1ap_log->error("Error unpacking NAS authentication response. Error: %s\n", liblte_error_text[err]); + return false; + } + + uint64_t imsi = 0; + for(int i=0;i<=14;i++){ + imsi += id_resp.mobile_id.imsi[i]*std::pow(10,14-i); + } + + m_s1ap_log->info("Id Response IMSI: %015lu\n", imsi); + ue_ctx->imsi = imsi; + + //Get Authentication Vectors from HSS + if(!m_hss->gen_auth_info_answer(imsi, ue_ctx->security_ctxt.k_asme, autn, rand, ue_ctx->security_ctxt.xres)) + { + m_s1ap_log->console("User not found. IMSI %015lu\n",imsi); + m_s1ap_log->info("User not found. IMSI %015lu\n",imsi); + return false; + } + + //Pack NAS Authentication Request in Downlink NAS Transport msg + pack_authentication_request(reply_msg, ue_ctx->enb_ue_s1ap_id, ue_ctx->mme_ue_s1ap_id, autn, rand); + + //Send reply to eNB + *reply_flag = true; + m_s1ap_log->info("DL NAS: Sent Athentication Request\n"); + //TODO Start T3460 Timer! + return true; + + return true; +} /*Packing/Unpacking helper functions*/ bool s1ap_nas_transport::unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, @@ -870,7 +921,56 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE return true; } +bool +s1ap_nas_transport::pack_identity_request(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id) +{ + srslte::byte_buffer_t *nas_buffer = m_pool->allocate(); + //Setup initiating message + LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu; + bzero(&tx_pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); + + tx_pdu.ext = false; + tx_pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE; + + LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *init = &tx_pdu.choice.initiatingMessage; + init->procedureCode = LIBLTE_S1AP_PROC_ID_DOWNLINKNASTRANSPORT; + init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DOWNLINKNASTRANSPORT; + + //Setup Dw NAS structure + LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT *dw_nas = &init->choice.DownlinkNASTransport; + dw_nas->ext=false; + dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = mme_ue_s1ap_id;//FIXME Change name + dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = enb_ue_s1ap_id; + dw_nas->HandoverRestrictionList_present=false; + dw_nas->SubscriberProfileIDforRFP_present=false; + + LIBLTE_MME_ID_REQUEST_MSG_STRUCT id_req; + id_req.id_type = LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI; + LIBLTE_ERROR_ENUM err = liblte_mme_pack_identity_request_msg(&id_req, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + if(err != LIBLTE_SUCCESS) + { + m_s1ap_log->error("Error packing Identity Request\n"); + m_s1ap_log->console("Error packing Identity REquest\n"); + return false; + } + + //Copy NAS PDU to Downlink NAS Trasport message buffer + memcpy(dw_nas->NAS_PDU.buffer, nas_buffer->msg, nas_buffer->N_bytes); + dw_nas->NAS_PDU.n_octets = nas_buffer->N_bytes; + + //Pack Downlink NAS Transport Message + err = liblte_s1ap_pack_s1ap_pdu(&tx_pdu, (LIBLTE_BYTE_MSG_STRUCT *) reply_msg); + if(err != LIBLTE_SUCCESS) + { + m_s1ap_log->error("Error packing Dw NAS Transport: Athentication Reject\n"); + m_s1ap_log->console("Error packing Downlink NAS Transport: Athentication Reject\n"); + return false; + } + + m_pool->deallocate(nas_buffer); + return true; +} /*Helper functions*/ void From 82bc1f7ff3159d4119a63b654da55195ce1a2d21 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 15 Jan 2018 12:56:37 +0000 Subject: [PATCH 156/172] Starting to add the ability of GUTI attach without requesting the ID, if the UE is already known. --- srsepc/src/mme/s1ap_nas_transport.cc | 29 ++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 52744119f..d8dc30877 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -107,6 +107,7 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA } //Create basic UE Ctx + ue_ctx_t *ue_ctx_ptr = &ue_ctx; ue_ctx.imsi = 0; ue_ctx.mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id(); //Get UE network capabilities @@ -152,20 +153,26 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA std::map::iterator it = m_s1ap->m_tmsi_to_s1ap_id.find(m_tmsi); if(it == m_s1ap->m_tmsi_to_s1ap_id.end()) { - //FIXME Send Id request + //Could not find IMSI from M-TMSI, send Id request m_s1ap_log->console("Could not find M-TMSI in attach request. Sending ID request\n"); m_s1ap_log->info("Could not find M-TMSI in attach request. Sending Id Request\n"); + ue_ctx.mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id(); m_s1ap->add_new_ue_ctx(ue_ctx); pack_identity_request(reply_buffer, ue_ctx.mme_ue_s1ap_id, ue_ctx.enb_ue_s1ap_id); *reply_flag = true; return true; } m_s1ap_log->console("Found M-TMSI: %d\n",m_tmsi); - ue_ctx_t *tmp = m_s1ap->find_ue_ctx(it->second); - if(tmp!=NULL) + ue_ctx_ptr = m_s1ap->find_ue_ctx(it->second); + if(ue_ctx_ptr!=NULL) { - m_s1ap_log->console("Found UE context. IMSI: %015lu\n",tmp->imsi); - imsi = tmp->imsi; + m_s1ap_log->console("Found UE context. IMSI: %015lu\n",ue_ctx_ptr->imsi); + imsi = ue_ctx_ptr->imsi; + } + else + { + m_s1ap_log->error("Found M-TMSI but could not find UE context\n"); + return false; } } m_s1ap_log->console("Attach request from IMSI: %015lu\n", imsi); @@ -173,7 +180,7 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA //Get Authentication Vectors from HSS - if(!m_hss->gen_auth_info_answer(imsi, ue_ctx.security_ctxt.k_asme, autn, rand, ue_ctx.security_ctxt.xres)) + if(!m_hss->gen_auth_info_answer(imsi, ue_ctx_ptr->security_ctxt.k_asme, autn, rand, ue_ctx_ptr->security_ctxt.xres)) { m_s1ap_log->console("User not found. IMSI %015lu\n",imsi); m_s1ap_log->info("User not found. IMSI %015lu\n",imsi); @@ -181,16 +188,15 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA } //Save UE context - ue_ctx.imsi = imsi; - ue_ctx.mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id(); - + //ue_ctx.imsi = imsi; if(attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI) { //IMSI attach requeires new UE ctxt + ue_ctx.mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id(); m_s1ap->add_new_ue_ctx(ue_ctx); } //Pack NAS Authentication Request in Downlink NAS Transport msg - pack_authentication_request(reply_buffer, ue_ctx.enb_ue_s1ap_id, ue_ctx.mme_ue_s1ap_id, autn, rand); + pack_authentication_request(reply_buffer, ue_ctx_ptr->enb_ue_s1ap_id, ue_ctx_ptr->mme_ue_s1ap_id, autn, rand); //Send reply to eNB *reply_flag = true; @@ -454,8 +460,7 @@ s1ap_nas_transport::handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_ //Send reply to eNB *reply_flag = true; m_s1ap_log->info("DL NAS: Sent Athentication Request\n"); - //TODO Start T3460 Timer! - return true; + //TODO Start T3460 Timer! return true; } From 0e1058c8d2bf648e6b82f2e43da9d01c178d724a Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 17 Jan 2018 10:24:26 +0000 Subject: [PATCH 157/172] Fixing small bug at filling out GUTI. --- srsepc/hdr/mme/s1ap_nas_transport.h | 3 + srsepc/src/mme/s1ap.cc | 5 +- srsepc/src/mme/s1ap_ctx_mngmt_proc.cc | 7 +- srsepc/src/mme/s1ap_nas_transport.cc | 218 +++++++++++++++++++++++--- srsepc/src/spgw/spgw.cc | 49 ++++-- 5 files changed, 243 insertions(+), 39 deletions(-) diff --git a/srsepc/hdr/mme/s1ap_nas_transport.h b/srsepc/hdr/mme/s1ap_nas_transport.h index ae8da16b3..8b63520b3 100644 --- a/srsepc/hdr/mme/s1ap_nas_transport.h +++ b/srsepc/hdr/mme/s1ap_nas_transport.h @@ -52,6 +52,7 @@ public: bool handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); bool handle_esm_information_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag); bool handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag); + bool handle_tracking_area_update_request(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag); bool unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req, LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req); @@ -65,6 +66,8 @@ public: bool pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT *erab_ctxt, struct srslte::gtpc_pdn_address_allocation_ie *paa, srslte::byte_buffer_t *nas_buffer); bool pack_identity_request(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id); + bool pack_emm_information(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id); + void log_unhandled_attach_request_ies(const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req); void log_unhandled_pdn_con_request_ies(const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req); void log_unhandled_initial_ue_message_ies(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue); diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index b9e303674..3f4003029 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -435,8 +435,9 @@ s1ap::activate_eps_bearer(uint32_t mme_s1ap_id, uint8_t ebi) uint32_t s1ap::allocate_m_tmsi(uint32_t mme_ue_s1ap_id) { - uint32_t m_tmsi = m_next_m_tmsi++; - m_tmsi_to_s1ap_id.insert(std::pair(m_tmsi,mme_ue_s1ap_id)); + //uint32_t m_tmsi = m_next_m_tmsi++; + //m_tmsi_to_s1ap_id.insert(std::pair(m_tmsi,mme_ue_s1ap_id)); + uint32_t m_tmsi = 0x0123; return m_tmsi; } diff --git a/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc index 185a6f8dd..8071942bb 100644 --- a/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc +++ b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc @@ -289,8 +289,11 @@ s1ap_ctx_mngmt_proc::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECON //There are active E-RABs, send delete session request m_mme_gtpc->send_delete_session_request(ue_ctx); } - m_s1ap->delete_ue_ctx(ue_ctx); - + //m_s1ap->delete_ue_ctx(ue_ctx); + for(int i=0;ierabs_ctx[i].state = ERAB_DEACTIVATED; + } //Delete UE context m_s1ap_log->info("Deleted UE Context.\n"); return true; diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index d8dc30877..432b3ce42 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -80,6 +80,7 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA { LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT attach_req; LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT pdn_con_req; + LIBLTE_MME_SERVICE_REQUEST_MSG_STRUCT service_req; uint64_t imsi = 0; uint8_t k_asme[32]; @@ -98,14 +99,35 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA //Log unhandled Initial UE message IEs log_unhandled_initial_ue_message_ies(init_ue); - //Get NAS Attach Request and PDN connectivity request messages - if(!unpack_initial_ue_message(init_ue, &attach_req,&pdn_con_req)) + /*Check whether NAS Attach Request or Service Request*/ + uint8_t pd, msg_type; + srslte::byte_buffer_t *nas_msg = m_pool->allocate(); + memcpy(nas_msg->msg, &init_ue->NAS_PDU.buffer, init_ue->NAS_PDU.n_octets); + nas_msg->N_bytes = init_ue->NAS_PDU.n_octets; + liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &pd, &msg_type); + if(msg_type == LIBLTE_MME_MSG_TYPE_ATTACH_REQUEST) { - //Could not decode the attach request and the PDN connectivity request. - m_s1ap_log->error("Could not unpack NAS Attach Request and PDN connectivity request.\n"); + //Get NAS Attach Request and PDN connectivity request messages + if(!unpack_initial_ue_message(init_ue, &attach_req,&pdn_con_req)) + { + //Could not decode the attach request and the PDN connectivity request. + m_s1ap_log->error("Could not unpack NAS Attach Request and PDN connectivity request.\n"); + return false; + } + } + else if(msg_type == LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST) + { + m_s1ap_log->info("Received Service Request \n"); + m_s1ap_log->console("Received Service Request \n"); + liblte_mme_unpack_service_request_msg((LIBLTE_BYTE_MSG_STRUCT*) nas_msg, &service_req); return false; } - + m_pool->deallocate(nas_msg); + /* + typedef struct{ + LIBLTE_MME_KSI_AND_SEQUENCE_NUMBER_STRUCT ksi_and_seq_num; + uint16 short_mac; + }LIBLTE_MME_SERVICE_REQUEST_MSG_STRUCT;*/ //Create basic UE Ctx ue_ctx_t *ue_ctx_ptr = &ue_ctx; ue_ctx.imsi = 0; @@ -143,22 +165,22 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA for(int i=0;i<=14;i++){ imsi += attach_req.eps_mobile_id.imsi[i]*std::pow(10,14-i); } - + m_s1ap_log->console("Attach Request -- IMSI-style attach request\n"); } else if(attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI) { //GUTI style attach - m_s1ap_log->console("Received GUTI-style attach request\n"); + m_s1ap_log->console("Attach Request -- GUTI-style attach request\n"); uint32_t m_tmsi = attach_req.eps_mobile_id.guti.m_tmsi; std::map::iterator it = m_s1ap->m_tmsi_to_s1ap_id.find(m_tmsi); if(it == m_s1ap->m_tmsi_to_s1ap_id.end()) { //Could not find IMSI from M-TMSI, send Id request - m_s1ap_log->console("Could not find M-TMSI in attach request. Sending ID request\n"); - m_s1ap_log->info("Could not find M-TMSI in attach request. Sending Id Request\n"); + m_s1ap_log->console("Attach Request -- Could not find M-TMSI. Sending ID request\n"); + m_s1ap_log->info("attach Request -- Could not find M-TMSI. Sending Id Request\n"); ue_ctx.mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id(); m_s1ap->add_new_ue_ctx(ue_ctx); - pack_identity_request(reply_buffer, ue_ctx.mme_ue_s1ap_id, ue_ctx.enb_ue_s1ap_id); + pack_identity_request(reply_buffer, ue_ctx.enb_ue_s1ap_id, ue_ctx.mme_ue_s1ap_id); *reply_flag = true; return true; } @@ -168,6 +190,9 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA { m_s1ap_log->console("Found UE context. IMSI: %015lu\n",ue_ctx_ptr->imsi); imsi = ue_ctx_ptr->imsi; + m_mme_gtpc->send_create_session_request(ue_ctx_ptr->imsi, ue_ctx_ptr->mme_ue_s1ap_id); + *reply_flag = false; //No reply needed + return true; } else { @@ -200,7 +225,8 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA //Send reply to eNB *reply_flag = true; - m_s1ap_log->info("DL NAS: Sent Athentication Request\n"); + m_s1ap_log->info("Sending Athentication Request\n"); + m_s1ap_log->console("Sending Athentication Request\n"); //TODO Start T3460 Timer! return true; } @@ -250,17 +276,21 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA handle_nas_attach_complete(nas_msg, ue_ctx, reply_buffer, reply_flag); ue_ctx->security_ctxt.ul_nas_count++; return true; //no need for reply. FIXME this should be better structured... - break; + break; case LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_RESPONSE: m_s1ap_log->info("UL NAS: Received ESM Information Response\n"); handle_esm_information_response(nas_msg, ue_ctx, reply_buffer, reply_flag); ue_ctx->security_ctxt.ul_nas_count++; - return true; + break; case LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE: m_s1ap_log->info("UL NAS: Received ID Response\n"); handle_identity_response(nas_msg, ue_ctx, reply_buffer, reply_flag); //ue_ctx->security_ctxt.ul_nas_count++; - return true; + break; + case LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_REQUEST: + m_s1ap_log->info("UL NAS: Tracking Area Update Request\n"); + handle_tracking_area_update_request(nas_msg, ue_ctx, reply_buffer, reply_flag); + break; default: m_s1ap_log->warning("Unhandled NAS message 0x%x\n", msg_type ); m_s1ap_log->console("Unhandled NAS message 0x%x\n", msg_type ); @@ -464,6 +494,79 @@ s1ap_nas_transport::handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_ return true; } + + +bool +s1ap_nas_transport::handle_tracking_area_update_request(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag) +{ + + /* + LIBLTE_ERROR_ENUM err = liblte_mme_unpack_tracking_area_update_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &tau_req); + if(err != LIBLTE_SUCCESS){ + m_s1ap_log->error("Error unpacking NAS authentication response. Error: %s\n", liblte_error_text[err]); + return false; + } + */ + //Setup initiating message + LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu; + bzero(&tx_pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); + + tx_pdu.ext = false; + tx_pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE; + + LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *init = &tx_pdu.choice.initiatingMessage; + init->procedureCode = LIBLTE_S1AP_PROC_ID_DOWNLINKNASTRANSPORT; + init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DOWNLINKNASTRANSPORT; + + //Setup Dw NAS structure + LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT *dw_nas = &init->choice.DownlinkNASTransport; + dw_nas->ext=false; + dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = ue_ctx->mme_ue_s1ap_id; + dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ue_ctx->enb_ue_s1ap_id; + dw_nas->HandoverRestrictionList_present=false; + dw_nas->SubscriberProfileIDforRFP_present=false; + m_s1ap_log->console("Tracking area accept to MME-UE S1AP Id %d\n", ue_ctx->mme_ue_s1ap_id); + + LIBLTE_MME_TRACKING_AREA_UPDATE_ACCEPT_MSG_STRUCT tau_acc; + /*typedef struct{ + LIBLTE_MME_GPRS_TIMER_STRUCT t3412; + LIBLTE_MME_EPS_MOBILE_ID_STRUCT guti; + LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_STRUCT tai_list; + LIBLTE_MME_EPS_BEARER_CONTEXT_STATUS_STRUCT eps_bearer_context_status; + LIBLTE_MME_LOCATION_AREA_ID_STRUCT lai; + LIBLTE_MME_MOBILE_ID_STRUCT ms_id; + LIBLTE_MME_GPRS_TIMER_STRUCT t3402; + LIBLTE_MME_GPRS_TIMER_STRUCT t3423; + LIBLTE_MME_PLMN_LIST_STRUCT equivalent_plmns; + LIBLTE_MME_EMERGENCY_NUMBER_LIST_STRUCT emerg_num_list; + LIBLTE_MME_EPS_NETWORK_FEATURE_SUPPORT_STRUCT eps_network_feature_support; + LIBLTE_MME_GPRS_TIMER_3_STRUCT t3412_ext; + LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_ENUM additional_update_result; + uint8 eps_update_result; + uint8 emm_cause; + bool t3412_present; + bool guti_present; + bool tai_list_present; + bool eps_bearer_context_status_present; + bool lai_present; + bool ms_id_present; + bool emm_cause_present; + bool t3402_present; + bool t3423_present; + bool equivalent_plmns_present; + bool emerg_num_list_present; + bool eps_network_feature_support_present; + bool additional_update_result_present; + bool t3412_ext_present; +}LIBLTE_MME_TRACKING_AREA_UPDATE_ACCEPT_MSG_STRUCT; +*/ + //Send reply to eNB + //*reply_flag = true; + + return true; +} + + /*Packing/Unpacking helper functions*/ bool s1ap_nas_transport::unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, @@ -830,19 +933,24 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE attach_accept.t3412.value = 30; // 30 minute periodic timer //FIXME: Set tai_list from config attach_accept.tai_list.N_tais = 1; - attach_accept.tai_list.tai[0].mcc = m_s1ap->m_s1ap_args.mcc; - attach_accept.tai_list.tai[0].mnc = m_s1ap->m_s1ap_args.mnc; + attach_accept.tai_list.tai[0].mcc = 1;//m_s1ap->m_s1ap_args.mcc; + attach_accept.tai_list.tai[0].mnc = 1;//m_s1ap->m_s1ap_args.mnc; attach_accept.tai_list.tai[0].tac = m_s1ap->m_s1ap_args.tac; //Allocate a GUTI ot the UE attach_accept.guti_present=true; attach_accept.guti.type_of_id = 6; //110 -> GUTI - attach_accept.guti.guti.mcc = m_s1ap->m_s1ap_args.mcc; - attach_accept.guti.guti.mnc = m_s1ap->m_s1ap_args.mnc; + attach_accept.guti.guti.mcc = 1;//m_s1ap->m_s1ap_args.mcc; + attach_accept.guti.guti.mnc = 1;//m_s1ap->m_s1ap_args.mnc; attach_accept.guti.guti.mme_group_id = 0x0001; - attach_accept.guti.guti.mme_code = 0x1a; + attach_accept.guti.guti.mme_code = 0xa1; attach_accept.guti.guti.m_tmsi = m_s1ap->allocate_m_tmsi(ue_ctx->mme_ue_s1ap_id); - + m_s1ap_log->debug("Allocated GUTI: MCC %d, MNC %d, MME Group Id %d, MME Code 0x%x, M-TMSI 0x%x\n", + attach_accept.guti.guti.mcc, + attach_accept.guti.guti.mnc, + attach_accept.guti.guti.mme_group_id, + attach_accept.guti.guti.mme_code, + attach_accept.guti.guti.m_tmsi); /* typedef struct{ uint32 m_tmsi; @@ -876,7 +984,6 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE memcpy(act_def_eps_bearer_context_req.pdn_addr.addr, &paa->ipv4, 4); //Set eps bearer id act_def_eps_bearer_context_req.eps_bearer_id = erab_ctxt->e_RAB_ID.E_RAB_ID; - printf("%d\n",act_def_eps_bearer_context_req.eps_bearer_id); act_def_eps_bearer_context_req.transaction_id_present = false; //set eps_qos act_def_eps_bearer_context_req.eps_qos.qci = erab_ctxt->e_RABlevelQoSParameters.qCI.QCI; @@ -977,6 +1084,75 @@ s1ap_nas_transport::pack_identity_request(srslte::byte_buffer_t *reply_msg, uint return true; } +bool +s1ap_nas_transport::pack_emm_information(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id) +{ + srslte::byte_buffer_t *nas_buffer = m_pool->allocate(); + + //Setup initiating message + LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu; + bzero(&tx_pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); + + tx_pdu.ext = false; + tx_pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE; + + LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *init = &tx_pdu.choice.initiatingMessage; + init->procedureCode = LIBLTE_S1AP_PROC_ID_DOWNLINKNASTRANSPORT; + init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DOWNLINKNASTRANSPORT; + + //Setup Dw NAS structure + LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT *dw_nas = &init->choice.DownlinkNASTransport; + dw_nas->ext=false; + dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = mme_ue_s1ap_id;//FIXME Change name + dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = enb_ue_s1ap_id; + dw_nas->HandoverRestrictionList_present=false; + dw_nas->SubscriberProfileIDforRFP_present=false; + + LIBLTE_MME_EMM_INFORMATION_MSG_STRUCT emm_info; + emm_info.full_net_name_present = true; + emm_info.full_net_name.name = std::string("srsLTE"); + emm_info.full_net_name.add_ci = LIBLTE_MME_ADD_CI_DONT_ADD; + emm_info.short_net_name_present = true; + emm_info.short_net_name.name = std::string("srsLTE"); + emm_info.short_net_name.add_ci = LIBLTE_MME_ADD_CI_DONT_ADD; + + emm_info.local_time_zone_present = false; + emm_info.utc_and_local_time_zone_present = false; + emm_info.net_dst_present = false; + + //Integrity check + ue_ctx_t * ue_ctx = m_s1ap->find_ue_ctx(mme_ue_s1ap_id); + if(ue_ctx == NULL) + { + return false; + } + uint8_t sec_hdr_type =2; + ue_ctx->security_ctxt.dl_nas_count++; + LIBLTE_ERROR_ENUM err = liblte_mme_pack_emm_information_msg(&emm_info, sec_hdr_type, ue_ctx->security_ctxt.dl_nas_count, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + if(err != LIBLTE_SUCCESS) + { + m_s1ap_log->error("Error packing Identity Request\n"); + m_s1ap_log->console("Error packing Identity REquest\n"); + return false; + } + + uint8_t mac[4]; + srslte::security_128_eia1 (&ue_ctx->security_ctxt.k_nas_int[16], + ue_ctx->security_ctxt.dl_nas_count, + 0, + SECURITY_DIRECTION_DOWNLINK, + &nas_buffer->msg[5], + nas_buffer->N_bytes - 5, + mac + ); + + memcpy(&nas_buffer->msg[1],mac,4); + + + m_s1ap_log->info("Packed \n"); + return true; +} + /*Helper functions*/ void s1ap_nas_transport::log_unhandled_attach_request_ies(const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req) diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index 23cf2a66c..b8a762ed6 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -33,6 +33,7 @@ #include #include #include +#include #include "spgw/spgw.h" #include "mme/mme_gtpc.h" #include "srslte/upper/gtpu.h" @@ -269,7 +270,7 @@ spgw::run_thread() struct sockaddr src_addr; socklen_t addrlen; - + struct iphdr *ip_pkt; int sgi = m_sgi_if; fd_set set; @@ -293,18 +294,37 @@ spgw::run_thread() //m_spgw_log->info("Data is available now.\n"); if (FD_ISSET(m_s1u, &set)) { - msg->N_bytes = recvfrom(m_s1u, msg->msg, SRSLTE_MAX_BUFFER_SIZE_BYTES, 0, &src_addr, &addrlen ); - //m_spgw_log->console("Received PDU from S1-U. Bytes %d\n", msg->N_bytes); - //m_spgw_log->debug("Received PDU from S1-U. Bytes %d\n", msg->N_bytes); - handle_s1u_pdu(msg); + msg->N_bytes = recvfrom(m_s1u, msg->msg, SRSLTE_MAX_BUFFER_SIZE_BYTES, 0, &src_addr, &addrlen ); + m_spgw_log->console("Received PDU from S1-U. Bytes %d\n", msg->N_bytes); + //m_spgw_log->debug("Received PDU from S1-U. Bytes %d\n", msg->N_bytes); + handle_s1u_pdu(msg); } if (FD_ISSET(m_sgi_if, &set)) { - //m_spgw_log->console("Received PDU from SGi\n"); - msg->N_bytes = read(sgi, msg->msg, SRSLTE_MAX_BUFFER_SIZE_BYTES); - //m_spgw_log->console("Received PDU from SGi. Bytes %d\n", msg->N_bytes); - //m_spgw_log->debug("Received PDU from SGi. Bytes %d\n", msg->N_bytes); - handle_sgi_pdu(msg); + msg->msg[0] = 0x0; + msg->N_bytes = read(sgi, msg->msg, SRSLTE_MAX_BUFFER_SIZE_BYTES); + m_spgw_log->console("Received PDU from SGi. Bytes %d\n", msg->N_bytes); + //m_spgw_log->debug("Received PDU from SGi. Bytes %d\n", msg->N_bytes); + if (msg->msg[0] != 0x60) { + //pdu->N_bytes = idx + N_bytes; + ip_pkt = (struct iphdr*)msg->msg; + + //log_h->debug_hex(pdu->msg, pdu->N_bytes, + // "Read %d bytes from TUN/TAP\n", + // N_bytes); + + // Check if entire packet was received + if(ntohs(ip_pkt->tot_len) == msg->N_bytes) + { + //Handle SGi PDU + msg->set_timestamp(); + handle_sgi_pdu(msg); + } + else + { + m_spgw_log->console("Did not read all bytes!!!"); + } + } } } else @@ -378,7 +398,8 @@ spgw::handle_sgi_pdu(srslte::byte_buffer_t *msg) m_spgw_log->error("Error sending packet to eNB\n"); return; } - //m_spgw_log->console("Sent packet to %s:%d. Bytes=%d\n",inet_ntoa(enb_addr.sin_addr), GTPU_RX_PORT,n); + m_spgw_log->console("Sent packet to %s:%d. Bytes=%d/%d\n",inet_ntoa(enb_addr.sin_addr), GTPU_RX_PORT,n,msg->N_bytes); + return; } @@ -386,11 +407,11 @@ spgw::handle_sgi_pdu(srslte::byte_buffer_t *msg) void spgw::handle_s1u_pdu(srslte::byte_buffer_t *msg) { - m_spgw_log->console("Received PDU from S1-U. Bytes=%d\n",msg->N_bytes); + //m_spgw_log->console("Received PDU from S1-U. Bytes=%d\n",msg->N_bytes); srslte::gtpu_header_t header; srslte::gtpu_read_header(msg, &header); - m_spgw_log->console("TEID 0x%x. Bytes=%d\n", header.teid, msg->N_bytes); + //m_spgw_log->console("TEID 0x%x. Bytes=%d\n", header.teid, msg->N_bytes); int n = write(m_sgi_if, msg->msg, msg->N_bytes); if(n<0) { @@ -398,7 +419,7 @@ spgw::handle_s1u_pdu(srslte::byte_buffer_t *msg) } else { - m_spgw_log->console("Forwarded packet to TUN interface\n"); + m_spgw_log->console("Forwarded packet to TUN interface. Bytes= %d/%d\n", n, msg->N_bytes); } return; } From cbc1e24e7eb03ab0bab08d2f91720b3bab600c12 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 17 Jan 2018 14:12:40 +0000 Subject: [PATCH 158/172] Cleaning up logging and printing. --- srsepc/src/hss/hss.cc | 1 - srsepc/src/mme/s1ap_nas_transport.cc | 59 ++++++++++++++++++---------- srsepc/src/spgw/spgw.cc | 30 +++----------- 3 files changed, 44 insertions(+), 46 deletions(-) diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index 659933c7b..a5f7597c1 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -375,7 +375,6 @@ hss::get_k_amf_op(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op ) } hss_ue_ctx_t *ue_ctx = ue_ctx_it->second; m_hss_log->info("Found User %015lu\n",imsi); - m_hss_log->console("Found User %015lu\n",imsi); memcpy(k,ue_ctx->key,16); memcpy(amf,ue_ctx->amf,2); memcpy(op,ue_ctx->op,16); diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 432b3ce42..6438dbe63 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -123,11 +123,7 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA return false; } m_pool->deallocate(nas_msg); - /* - typedef struct{ - LIBLTE_MME_KSI_AND_SEQUENCE_NUMBER_STRUCT ksi_and_seq_num; - uint16 short_mac; - }LIBLTE_MME_SERVICE_REQUEST_MSG_STRUCT;*/ + //Create basic UE Ctx ue_ctx_t *ue_ctx_ptr = &ue_ctx; ue_ctx.imsi = 0; @@ -143,7 +139,7 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA ue_ctx.procedure_transaction_id = pdn_con_req.proc_transaction_id; //Save whether ESM information transfer is necessary ue_ctx.eit = pdn_con_req.esm_info_transfer_flag_present; - m_s1ap_log->console("EPS Bearer id: %d\n", eps_bearer_id); + //m_s1ap_log->console("EPS Bearer id: %d\n", eps_bearer_id); //Initialize NAS count ue_ctx.security_ctxt.ul_nas_count = 0; ue_ctx.security_ctxt.dl_nas_count = 0; @@ -155,8 +151,6 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA ue_ctx.erabs_ctx[i].state = ERAB_DEACTIVATED; ue_ctx.erabs_ctx[i].erab_id = i; } - - //Get UE Identity if(attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI) { @@ -176,8 +170,8 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA if(it == m_s1ap->m_tmsi_to_s1ap_id.end()) { //Could not find IMSI from M-TMSI, send Id request - m_s1ap_log->console("Attach Request -- Could not find M-TMSI. Sending ID request\n"); - m_s1ap_log->info("attach Request -- Could not find M-TMSI. Sending Id Request\n"); + m_s1ap_log->console("Attach Request -- Could not find M-TMSI=0x%x. Sending ID request\n",m_tmsi); + m_s1ap_log->info("Attach Request -- Could not find M-TMSI=0x%d. Sending Id Request\n", m_tmsi); ue_ctx.mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id(); m_s1ap->add_new_ue_ctx(ue_ctx); pack_identity_request(reply_buffer, ue_ctx.enb_ue_s1ap_id, ue_ctx.mme_ue_s1ap_id); @@ -200,9 +194,31 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA return false; } } - m_s1ap_log->console("Attach request from IMSI: %015lu\n", imsi); - m_s1ap_log->info("Attach request from IMSI: %015lu\n", imsi); - + m_s1ap_log->console("Attach request -- IMSI: %015lu\n", imsi); + m_s1ap_log->info("Attach request -- IMSI: %015lu\n", imsi); + m_s1ap_log->console("Attach request -- eNB-UE S1AP Id: %d, MME-UE S1AP Id: %d\n", ue_ctx_ptr->enb_ue_s1ap_id, ue_ctx_ptr->mme_ue_s1ap_id); + m_s1ap_log->console("Attach Request -- UE Network Capabilities EEA: %d%d%d%d%d%d%d%d\n", + attach_req.ue_network_cap.eea[0], + attach_req.ue_network_cap.eea[1], + attach_req.ue_network_cap.eea[2], + attach_req.ue_network_cap.eea[3], + attach_req.ue_network_cap.eea[4], + attach_req.ue_network_cap.eea[5], + attach_req.ue_network_cap.eea[6], + attach_req.ue_network_cap.eea[7]); + m_s1ap_log->console("Attach Request -- UE Network Capabilities EIA: %d%d%d%d%d%d%d%d\n", + attach_req.ue_network_cap.eia[0], + attach_req.ue_network_cap.eia[1], + attach_req.ue_network_cap.eia[2], + attach_req.ue_network_cap.eia[3], + attach_req.ue_network_cap.eia[4], + attach_req.ue_network_cap.eia[5], + attach_req.ue_network_cap.eia[6], + attach_req.ue_network_cap.eia[7]); + m_s1ap_log->console("Attach Request -- MS Network Capabilities Present: %s\n", attach_req.ms_network_cap_present ? "true" : "false"); + m_s1ap_log->console("PDN Connectivity Request -- EPS Bearer Identity requested: %d\n", pdn_con_req.eps_bearer_id); + m_s1ap_log->console("PDN Connectivity Request -- Procedure Transaction Id: %d\n", pdn_con_req.proc_transaction_id); + m_s1ap_log->console("PDN Connectivity Request -- ESM Information Transfer requested: %s\n", pdn_con_req.esm_info_transfer_flag_present ? "true" : "false"); //Get Authentication Vectors from HSS if(!m_hss->gen_auth_info_answer(imsi, ue_ctx_ptr->security_ctxt.k_asme, autn, rand, ue_ctx_ptr->security_ctxt.xres)) @@ -263,27 +279,30 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA switch (msg_type) { case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE: + m_s1ap_log->info("Uplink NAS: Received Authentication Response\n"); + m_s1ap_log->console("Uplink NAS: Received Authentication Response\n"); handle_nas_authentication_response(nas_msg, ue_ctx, reply_buffer, reply_flag); - m_s1ap_log->info("UL NAS: Received Authentication Response\n"); break; case LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMPLETE: - m_s1ap_log->info("UL NAS: Received Security Mode Complete\n"); + m_s1ap_log->info("Uplink NAS: Received Security Mode Complete\n"); + m_s1ap_log->console("Uplink NAS: Received Security Mode Complete\n"); handle_nas_security_mode_complete(nas_msg, ue_ctx, reply_buffer, reply_flag); - return true; //no need for reply. FIXME this should be better structured... break; case LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE: - m_s1ap_log->info("UL NAS: Received Attach Complete\n"); + m_s1ap_log->info("Uplink NAS: Received Attach Complete\n"); + m_s1ap_log->console("Uplink NAS: Received Attach Complete\n"); handle_nas_attach_complete(nas_msg, ue_ctx, reply_buffer, reply_flag); ue_ctx->security_ctxt.ul_nas_count++; - return true; //no need for reply. FIXME this should be better structured... break; case LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_RESPONSE: - m_s1ap_log->info("UL NAS: Received ESM Information Response\n"); + m_s1ap_log->info("Uplink NAS: Received ESM Information Response\n"); + m_s1ap_log->console("Uplink NAS: Received ESM Information Response\n"); handle_esm_information_response(nas_msg, ue_ctx, reply_buffer, reply_flag); ue_ctx->security_ctxt.ul_nas_count++; break; case LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE: - m_s1ap_log->info("UL NAS: Received ID Response\n"); + m_s1ap_log->info("Uplink NAS: Received Identity Response\n"); + m_s1ap_log->info("Uplink NAS: Received Identity Response\n"); handle_identity_response(nas_msg, ue_ctx, reply_buffer, reply_flag); //ue_ctx->security_ctxt.ul_nas_count++; break; diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index b8a762ed6..b39572f11 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -301,30 +301,10 @@ spgw::run_thread() } if (FD_ISSET(m_sgi_if, &set)) { - msg->msg[0] = 0x0; msg->N_bytes = read(sgi, msg->msg, SRSLTE_MAX_BUFFER_SIZE_BYTES); - m_spgw_log->console("Received PDU from SGi. Bytes %d\n", msg->N_bytes); + //m_spgw_log->console("Received PDU from SGi. Bytes %d\n", msg->N_bytes); //m_spgw_log->debug("Received PDU from SGi. Bytes %d\n", msg->N_bytes); - if (msg->msg[0] != 0x60) { - //pdu->N_bytes = idx + N_bytes; - ip_pkt = (struct iphdr*)msg->msg; - - //log_h->debug_hex(pdu->msg, pdu->N_bytes, - // "Read %d bytes from TUN/TAP\n", - // N_bytes); - - // Check if entire packet was received - if(ntohs(ip_pkt->tot_len) == msg->N_bytes) - { - //Handle SGi PDU - msg->set_timestamp(); - handle_sgi_pdu(msg); - } - else - { - m_spgw_log->console("Did not read all bytes!!!"); - } - } + handle_sgi_pdu(msg); } } else @@ -375,7 +355,7 @@ spgw::handle_sgi_pdu(srslte::byte_buffer_t *msg) enb_addr.sin_family = AF_INET; enb_addr.sin_port = htons(GTPU_RX_PORT); enb_addr.sin_addr.s_addr = enb_fteid.ipv4; - m_spgw_log->console("UE F-TEID found, TEID 0x%x, eNB IP %s\n", enb_fteid.teid, inet_ntoa(enb_addr.sin_addr)); + //m_spgw_log->console("UE F-TEID found, TEID 0x%x, eNB IP %s\n", enb_fteid.teid, inet_ntoa(enb_addr.sin_addr)); //Setup GTP-U header srslte::gtpu_header_t header; @@ -398,7 +378,7 @@ spgw::handle_sgi_pdu(srslte::byte_buffer_t *msg) m_spgw_log->error("Error sending packet to eNB\n"); return; } - m_spgw_log->console("Sent packet to %s:%d. Bytes=%d/%d\n",inet_ntoa(enb_addr.sin_addr), GTPU_RX_PORT,n,msg->N_bytes); + //m_spgw_log->console("Sent packet to %s:%d. Bytes=%d/%d\n",inet_ntoa(enb_addr.sin_addr), GTPU_RX_PORT,n,msg->N_bytes); return; } @@ -419,7 +399,7 @@ spgw::handle_s1u_pdu(srslte::byte_buffer_t *msg) } else { - m_spgw_log->console("Forwarded packet to TUN interface. Bytes= %d/%d\n", n, msg->N_bytes); + //m_spgw_log->console("Forwarded packet to TUN interface. Bytes= %d/%d\n", n, msg->N_bytes); } return; } From 074cf4526ff630c06c4efd111f242db3dd9eb497 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 17 Jan 2018 19:50:24 +0000 Subject: [PATCH 159/172] Cleaned up the handling of the Initial UE message. --- srsepc/hdr/mme/s1ap_nas_transport.h | 18 ++ srsepc/src/mme/s1ap.cc | 2 +- srsepc/src/mme/s1ap_nas_transport.cc | 256 +++++++++++++++++++++++++-- 3 files changed, 261 insertions(+), 15 deletions(-) diff --git a/srsepc/hdr/mme/s1ap_nas_transport.h b/srsepc/hdr/mme/s1ap_nas_transport.h index 8b63520b3..de1d67551 100644 --- a/srsepc/hdr/mme/s1ap_nas_transport.h +++ b/srsepc/hdr/mme/s1ap_nas_transport.h @@ -47,6 +47,24 @@ public: bool handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, struct sctp_sndrcvinfo *enb_sri, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); bool handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, struct sctp_sndrcvinfo *enb_sri, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); + bool handle_nas_attach_request( uint32_t enb_ue_s1ap_id, + const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT &attach_req, + const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT &pdn_con_req, + srslte::byte_buffer_t *reply_buffer, + bool* reply_flag, + struct sctp_sndrcvinfo *enb_sri); + bool handle_nas_imsi_attach_request(uint32_t enb_ue_s1ap_id, + const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT &attach_req, + const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT &pdn_con_req, + srslte::byte_buffer_t *reply_buffer, + bool* reply_flag, + struct sctp_sndrcvinfo *enb_sri); + bool handle_nas_guti_attach_request(uint32_t enb_ue_s1ap_id, + const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT &attach_req, + const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT &pdn_con_req, + srslte::byte_buffer_t *reply_buffer, + bool* reply_flag, + struct sctp_sndrcvinfo *enb_sri); bool handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_buffer, bool* reply_flag); bool handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); bool handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 3f4003029..07563e7ca 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -285,7 +285,7 @@ s1ap::handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, stru ssize_t n_sent = sctp_send(m_s1mme,reply_buffer->msg, reply_buffer->N_bytes, enb_sri, 0); if(n_sent == -1) { - m_s1ap_log->console("Failed to send S1 Setup Setup Reply"); + m_s1ap_log->console("Failed to send S1 Setup Setup Reply\n"); m_pool->deallocate(reply_buffer); return false; } diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 6438dbe63..fb8687277 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -82,19 +82,11 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT pdn_con_req; LIBLTE_MME_SERVICE_REQUEST_MSG_STRUCT service_req; - uint64_t imsi = 0; - uint8_t k_asme[32]; - uint8_t autn[16]; - uint8_t rand[6]; - uint8_t xres[8]; - - ue_ctx_t ue_ctx; - m_s1ap_log->console("Received Initial UE Message.\n"); m_s1ap_log->info("Received Initial UE Message.\n"); //Get info from initial UE message - ue_ctx.enb_ue_s1ap_id = init_ue->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; + uint32_t enb_ue_s1ap_id = init_ue->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; //Log unhandled Initial UE message IEs log_unhandled_initial_ue_message_ies(init_ue); @@ -108,12 +100,26 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA if(msg_type == LIBLTE_MME_MSG_TYPE_ATTACH_REQUEST) { //Get NAS Attach Request and PDN connectivity request messages - if(!unpack_initial_ue_message(init_ue, &attach_req,&pdn_con_req)) + LIBLTE_ERROR_ENUM err = liblte_mme_unpack_attach_request_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &attach_req); + if(err != LIBLTE_SUCCESS){ + m_s1ap_log->error("Error unpacking NAS attach request. Error: %s\n", liblte_error_text[err]); + m_pool->deallocate(nas_msg); + return false; + } + /*Get PDN Connectivity Request*/ + err = liblte_mme_unpack_pdn_connectivity_request_msg(&attach_req.esm_msg, &pdn_con_req); + if(err != LIBLTE_SUCCESS){ + m_s1ap_log->error("Error unpacking NAS PDN Connectivity Request. Error: %s\n", liblte_error_text[err]); + m_pool->deallocate(nas_msg); + return false; + } + /* if(!unpack_initial_ue_message(init_ue, &attach_req,&pdn_con_req)) { //Could not decode the attach request and the PDN connectivity request. m_s1ap_log->error("Could not unpack NAS Attach Request and PDN connectivity request.\n"); return false; - } + }*/ + handle_nas_attach_request(enb_ue_s1ap_id, attach_req,pdn_con_req,reply_buffer,reply_flag, enb_sri); } else if(msg_type == LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST) { @@ -123,7 +129,9 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA return false; } m_pool->deallocate(nas_msg); + return true; + /* //Create basic UE Ctx ue_ctx_t *ue_ctx_ptr = &ue_ctx; ue_ctx.imsi = 0; @@ -244,6 +252,7 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA m_s1ap_log->info("Sending Athentication Request\n"); m_s1ap_log->console("Sending Athentication Request\n"); //TODO Start T3460 Timer! + */ return true; } @@ -302,7 +311,7 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA break; case LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE: m_s1ap_log->info("Uplink NAS: Received Identity Response\n"); - m_s1ap_log->info("Uplink NAS: Received Identity Response\n"); + m_s1ap_log->console("Uplink NAS: Received Identity Response\n"); handle_identity_response(nas_msg, ue_ctx, reply_buffer, reply_flag); //ue_ctx->security_ctxt.ul_nas_count++; break; @@ -326,6 +335,225 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA return true; } +bool +s1ap_nas_transport::handle_nas_attach_request(uint32_t enb_ue_s1ap_id, + const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT &attach_req, + const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT &pdn_con_req, + srslte::byte_buffer_t *reply_buffer, + bool* reply_flag, + struct sctp_sndrcvinfo *enb_sri) +{ + //Get attach type from attach request + if(attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI) + { + m_s1ap_log->console("Attach Request -- IMSI-style attach request\n"); + m_s1ap_log->info("Attach Request -- IMSI-style attach request\n"); + handle_nas_imsi_attach_request(enb_ue_s1ap_id, attach_req, pdn_con_req, reply_buffer, reply_flag, enb_sri); + } + else if(attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI) + { + m_s1ap_log->console("Attach Request -- GUTI-style attach request\n"); + m_s1ap_log->info("Attach Request -- GUTI-style attach request\n"); + handle_nas_guti_attach_request(enb_ue_s1ap_id, attach_req, pdn_con_req, reply_buffer, reply_flag, enb_sri); + } + else + { + m_s1ap_log->error("Unhandle Mobile Id type in attach request\n"); + return false; + } + return true; +} + +bool +s1ap_nas_transport::handle_nas_imsi_attach_request(uint32_t enb_ue_s1ap_id, + const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT &attach_req, + const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT &pdn_con_req, + srslte::byte_buffer_t *reply_buffer, + bool* reply_flag, + struct sctp_sndrcvinfo *enb_sri) +{ + uint8_t k_asme[32]; + uint8_t autn[16]; + uint8_t rand[6]; + uint8_t xres[8]; + + ue_ctx_t ue_ctx; + ue_ctx.imsi = 0; + ue_ctx.enb_ue_s1ap_id = enb_ue_s1ap_id; + ue_ctx.mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id(); + + //Save UE network capabilities + memcpy(&ue_ctx.ue_network_cap, &attach_req.ue_network_cap, sizeof(LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT)); + ue_ctx.ms_network_cap_present = attach_req.ms_network_cap_present; + if(attach_req.ms_network_cap_present) + { + memcpy(&ue_ctx.ms_network_cap, &attach_req.ms_network_cap, sizeof(LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT)); + } + uint8_t eps_bearer_id = pdn_con_req.eps_bearer_id; //TODO: Unused + ue_ctx.procedure_transaction_id = pdn_con_req.proc_transaction_id; + + //Save whether ESM information transfer is necessary + ue_ctx.eit = pdn_con_req.esm_info_transfer_flag_present; + //m_s1ap_log->console("EPS Bearer id: %d\n", eps_bearer_id); + //Initialize NAS count + ue_ctx.security_ctxt.ul_nas_count = 0; + ue_ctx.security_ctxt.dl_nas_count = 0; + //Add eNB info to UE ctxt + memcpy(&ue_ctx.enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); + //Initialize E-RABs + for(uint i = 0 ; i< MAX_ERABS_PER_UE; i++) + { + ue_ctx.erabs_ctx[i].state = ERAB_DEACTIVATED; + ue_ctx.erabs_ctx[i].erab_id = i; + } + + //IMSI style attach + ue_ctx.imsi = 0; + for(int i=0;i<=14;i++){ + ue_ctx.imsi += attach_req.eps_mobile_id.imsi[i]*std::pow(10,14-i); + } + + m_s1ap_log->console("Attach request -- IMSI: %015lu\n", ue_ctx.imsi); + m_s1ap_log->info("Attach request -- IMSI: %015lu\n", ue_ctx.imsi); + m_s1ap_log->console("Attach request -- eNB-UE S1AP Id: %d, MME-UE S1AP Id: %d\n", ue_ctx.enb_ue_s1ap_id, ue_ctx.mme_ue_s1ap_id); + m_s1ap_log->console("Attach Request -- UE Network Capabilities EEA: %d%d%d%d%d%d%d%d\n", + attach_req.ue_network_cap.eea[0], + attach_req.ue_network_cap.eea[1], + attach_req.ue_network_cap.eea[2], + attach_req.ue_network_cap.eea[3], + attach_req.ue_network_cap.eea[4], + attach_req.ue_network_cap.eea[5], + attach_req.ue_network_cap.eea[6], + attach_req.ue_network_cap.eea[7]); + m_s1ap_log->console("Attach Request -- UE Network Capabilities EIA: %d%d%d%d%d%d%d%d\n", + attach_req.ue_network_cap.eia[0], + attach_req.ue_network_cap.eia[1], + attach_req.ue_network_cap.eia[2], + attach_req.ue_network_cap.eia[3], + attach_req.ue_network_cap.eia[4], + attach_req.ue_network_cap.eia[5], + attach_req.ue_network_cap.eia[6], + attach_req.ue_network_cap.eia[7]); + m_s1ap_log->console("Attach Request -- MS Network Capabilities Present: %s\n", attach_req.ms_network_cap_present ? "true" : "false"); + m_s1ap_log->console("PDN Connectivity Request -- EPS Bearer Identity requested: %d\n", pdn_con_req.eps_bearer_id); + m_s1ap_log->console("PDN Connectivity Request -- Procedure Transaction Id: %d\n", pdn_con_req.proc_transaction_id); + m_s1ap_log->console("PDN Connectivity Request -- ESM Information Transfer requested: %s\n", pdn_con_req.esm_info_transfer_flag_present ? "true" : "false"); + + //Get Authentication Vectors from HSS + if(!m_hss->gen_auth_info_answer(ue_ctx.imsi, ue_ctx.security_ctxt.k_asme, autn, rand, ue_ctx.security_ctxt.xres)) + { + m_s1ap_log->console("User not found. IMSI %015lu\n",ue_ctx.imsi); + m_s1ap_log->info("User not found. IMSI %015lu\n",ue_ctx.imsi); + return false; + } + + m_s1ap->add_new_ue_ctx(ue_ctx); + //Pack NAS Authentication Request in Downlink NAS Transport msg + pack_authentication_request(reply_buffer, ue_ctx.enb_ue_s1ap_id, ue_ctx.mme_ue_s1ap_id, autn, rand); + + //Send reply to eNB + *reply_flag = true; + m_s1ap_log->info("Downlink NAS: Sending Athentication Request\n"); + m_s1ap_log->console("Downlink NAS: Sending Athentication Request\n"); + return true; +} + +bool +s1ap_nas_transport::handle_nas_guti_attach_request(uint32_t enb_ue_s1ap_id, + const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT &attach_req, + const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT &pdn_con_req, + srslte::byte_buffer_t *reply_buffer, + bool* reply_flag, + struct sctp_sndrcvinfo *enb_sri) +{ + //GUTI style attach + uint32_t m_tmsi = attach_req.eps_mobile_id.guti.m_tmsi; + std::map::iterator it = m_s1ap->m_tmsi_to_s1ap_id.find(m_tmsi); + if(it == m_s1ap->m_tmsi_to_s1ap_id.end()) + { + //Could not find IMSI from M-TMSI, send Id request + ue_ctx_t ue_ctx; + ue_ctx.imsi = 0; + ue_ctx.enb_ue_s1ap_id = enb_ue_s1ap_id; + ue_ctx.mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id(); + + //Save UE network capabilities + memcpy(&ue_ctx.ue_network_cap, &attach_req.ue_network_cap, sizeof(LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT)); + ue_ctx.ms_network_cap_present = attach_req.ms_network_cap_present; + if(attach_req.ms_network_cap_present) + { + memcpy(&ue_ctx.ms_network_cap, &attach_req.ms_network_cap, sizeof(LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT)); + } + uint8_t eps_bearer_id = pdn_con_req.eps_bearer_id; //TODO: Unused + ue_ctx.procedure_transaction_id = pdn_con_req.proc_transaction_id; + + //Save whether ESM information transfer is necessary + ue_ctx.eit = pdn_con_req.esm_info_transfer_flag_present; + //m_s1ap_log->console("EPS Bearer id: %d\n", eps_bearer_id); + //Initialize NAS count + ue_ctx.security_ctxt.ul_nas_count = 0; + ue_ctx.security_ctxt.dl_nas_count = 0; + //Add eNB info to UE ctxt + memcpy(&ue_ctx.enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); + //Initialize E-RABs + for(uint i = 0 ; i< MAX_ERABS_PER_UE; i++) + { + ue_ctx.erabs_ctx[i].state = ERAB_DEACTIVATED; + ue_ctx.erabs_ctx[i].erab_id = i; + } + m_s1ap_log->console("Attach request -- IMSI: %015lu\n", ue_ctx.imsi); + m_s1ap_log->info("Attach request -- IMSI: %015lu\n", ue_ctx.imsi); + m_s1ap_log->console("Attach request -- eNB-UE S1AP Id: %d, MME-UE S1AP Id: %d\n", ue_ctx.enb_ue_s1ap_id, ue_ctx.mme_ue_s1ap_id); + m_s1ap_log->console("Attach Request -- UE Network Capabilities EEA: %d%d%d%d%d%d%d%d\n", + attach_req.ue_network_cap.eea[0], + attach_req.ue_network_cap.eea[1], + attach_req.ue_network_cap.eea[2], + attach_req.ue_network_cap.eea[3], + attach_req.ue_network_cap.eea[4], + attach_req.ue_network_cap.eea[5], + attach_req.ue_network_cap.eea[6], + attach_req.ue_network_cap.eea[7]); + m_s1ap_log->console("Attach Request -- UE Network Capabilities EIA: %d%d%d%d%d%d%d%d\n", + attach_req.ue_network_cap.eia[0], + attach_req.ue_network_cap.eia[1], + attach_req.ue_network_cap.eia[2], + attach_req.ue_network_cap.eia[3], + attach_req.ue_network_cap.eia[4], + attach_req.ue_network_cap.eia[5], + attach_req.ue_network_cap.eia[6], + attach_req.ue_network_cap.eia[7]); + m_s1ap_log->console("Attach Request -- MS Network Capabilities Present: %s\n", attach_req.ms_network_cap_present ? "true" : "false"); + m_s1ap_log->console("PDN Connectivity Request -- EPS Bearer Identity requested: %d\n", pdn_con_req.eps_bearer_id); + m_s1ap_log->console("PDN Connectivity Request -- Procedure Transaction Id: %d\n", pdn_con_req.proc_transaction_id); + m_s1ap_log->console("PDN Connectivity Request -- ESM Information Transfer requested: %s\n", pdn_con_req.esm_info_transfer_flag_present ? "true" : "false"); + + m_s1ap_log->console("Could not find M-TMSI=0x%x. Sending ID request\n",m_tmsi); + m_s1ap_log->info("Could not find M-TMSI=0x%d. Sending Id Request\n", m_tmsi); + ue_ctx.mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id(); + m_s1ap->add_new_ue_ctx(ue_ctx); + pack_identity_request(reply_buffer, ue_ctx.enb_ue_s1ap_id, ue_ctx.mme_ue_s1ap_id); + *reply_flag = true; + return true; + } + else{ + m_s1ap_log->console("Attach Request -- Found M-TMSI: %d\n",m_tmsi); + ue_ctx_t *ue_ctx_ptr = m_s1ap->find_ue_ctx(it->second); + if(ue_ctx_ptr!=NULL) + { + m_s1ap_log->console("Found UE context. IMSI: %015lu\n",ue_ctx_ptr->imsi); + m_mme_gtpc->send_create_session_request(ue_ctx_ptr->imsi, ue_ctx_ptr->mme_ue_s1ap_id); + *reply_flag = false; //No reply needed + return true; + } + else + { + m_s1ap_log->error("Found M-TMSI but could not find UE context\n"); + return false; + } + } + return true; +} + bool s1ap_nas_transport::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_buffer, bool* reply_flag) { @@ -491,8 +719,8 @@ s1ap_nas_transport::handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_ for(int i=0;i<=14;i++){ imsi += id_resp.mobile_id.imsi[i]*std::pow(10,14-i); } - - m_s1ap_log->info("Id Response IMSI: %015lu\n", imsi); + m_s1ap_log->info("Id Response -- IMSI: %015lu\n", imsi); + m_s1ap_log->info("Id Response -- IMSI: %015lu\n", imsi); ue_ctx->imsi = imsi; //Get Authentication Vectors from HSS From 3227bc8e66e1f8cd6dc0da5e85179dc16444b085 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 17 Jan 2018 19:55:00 +0000 Subject: [PATCH 160/172] Deleting commented out and unused code. --- srsepc/hdr/mme/s1ap_nas_transport.h | 2 - srsepc/src/mme/s1ap_nas_transport.cc | 180 --------------------------- 2 files changed, 182 deletions(-) diff --git a/srsepc/hdr/mme/s1ap_nas_transport.h b/srsepc/hdr/mme/s1ap_nas_transport.h index de1d67551..e37ce4d61 100644 --- a/srsepc/hdr/mme/s1ap_nas_transport.h +++ b/srsepc/hdr/mme/s1ap_nas_transport.h @@ -72,8 +72,6 @@ public: bool handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag); bool handle_tracking_area_update_request(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag); - bool unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req, LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req); - bool pack_authentication_request(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t next_mme_ue_s1ap_id, uint8_t *autn,uint8_t *rand); bool pack_authentication_reject(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id); bool unpack_authentication_response(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT *auth_resp); diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index fb8687277..0277b3763 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -113,12 +113,6 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA m_pool->deallocate(nas_msg); return false; } - /* if(!unpack_initial_ue_message(init_ue, &attach_req,&pdn_con_req)) - { - //Could not decode the attach request and the PDN connectivity request. - m_s1ap_log->error("Could not unpack NAS Attach Request and PDN connectivity request.\n"); - return false; - }*/ handle_nas_attach_request(enb_ue_s1ap_id, attach_req,pdn_con_req,reply_buffer,reply_flag, enb_sri); } else if(msg_type == LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST) @@ -129,130 +123,7 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA return false; } m_pool->deallocate(nas_msg); - return true; - /* - //Create basic UE Ctx - ue_ctx_t *ue_ctx_ptr = &ue_ctx; - ue_ctx.imsi = 0; - ue_ctx.mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id(); - //Get UE network capabilities - memcpy(&ue_ctx.ue_network_cap, &attach_req.ue_network_cap, sizeof(LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT)); - ue_ctx.ms_network_cap_present = attach_req.ms_network_cap_present; - if(attach_req.ms_network_cap_present) - { - memcpy(&ue_ctx.ms_network_cap, &attach_req.ms_network_cap, sizeof(LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT)); - } - uint8_t eps_bearer_id = pdn_con_req.eps_bearer_id; //TODO: Unused - ue_ctx.procedure_transaction_id = pdn_con_req.proc_transaction_id; - //Save whether ESM information transfer is necessary - ue_ctx.eit = pdn_con_req.esm_info_transfer_flag_present; - //m_s1ap_log->console("EPS Bearer id: %d\n", eps_bearer_id); - //Initialize NAS count - ue_ctx.security_ctxt.ul_nas_count = 0; - ue_ctx.security_ctxt.dl_nas_count = 0; - //Add eNB info to UE ctxt - memcpy(&ue_ctx.enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); - //Initialize E-RABs - for(uint i = 0 ; i< MAX_ERABS_PER_UE; i++) - { - ue_ctx.erabs_ctx[i].state = ERAB_DEACTIVATED; - ue_ctx.erabs_ctx[i].erab_id = i; - } - //Get UE Identity - if(attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI) - { - //IMSI style attach - imsi = 0; - for(int i=0;i<=14;i++){ - imsi += attach_req.eps_mobile_id.imsi[i]*std::pow(10,14-i); - } - m_s1ap_log->console("Attach Request -- IMSI-style attach request\n"); - } - else if(attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI) - { - //GUTI style attach - m_s1ap_log->console("Attach Request -- GUTI-style attach request\n"); - uint32_t m_tmsi = attach_req.eps_mobile_id.guti.m_tmsi; - std::map::iterator it = m_s1ap->m_tmsi_to_s1ap_id.find(m_tmsi); - if(it == m_s1ap->m_tmsi_to_s1ap_id.end()) - { - //Could not find IMSI from M-TMSI, send Id request - m_s1ap_log->console("Attach Request -- Could not find M-TMSI=0x%x. Sending ID request\n",m_tmsi); - m_s1ap_log->info("Attach Request -- Could not find M-TMSI=0x%d. Sending Id Request\n", m_tmsi); - ue_ctx.mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id(); - m_s1ap->add_new_ue_ctx(ue_ctx); - pack_identity_request(reply_buffer, ue_ctx.enb_ue_s1ap_id, ue_ctx.mme_ue_s1ap_id); - *reply_flag = true; - return true; - } - m_s1ap_log->console("Found M-TMSI: %d\n",m_tmsi); - ue_ctx_ptr = m_s1ap->find_ue_ctx(it->second); - if(ue_ctx_ptr!=NULL) - { - m_s1ap_log->console("Found UE context. IMSI: %015lu\n",ue_ctx_ptr->imsi); - imsi = ue_ctx_ptr->imsi; - m_mme_gtpc->send_create_session_request(ue_ctx_ptr->imsi, ue_ctx_ptr->mme_ue_s1ap_id); - *reply_flag = false; //No reply needed - return true; - } - else - { - m_s1ap_log->error("Found M-TMSI but could not find UE context\n"); - return false; - } - } - m_s1ap_log->console("Attach request -- IMSI: %015lu\n", imsi); - m_s1ap_log->info("Attach request -- IMSI: %015lu\n", imsi); - m_s1ap_log->console("Attach request -- eNB-UE S1AP Id: %d, MME-UE S1AP Id: %d\n", ue_ctx_ptr->enb_ue_s1ap_id, ue_ctx_ptr->mme_ue_s1ap_id); - m_s1ap_log->console("Attach Request -- UE Network Capabilities EEA: %d%d%d%d%d%d%d%d\n", - attach_req.ue_network_cap.eea[0], - attach_req.ue_network_cap.eea[1], - attach_req.ue_network_cap.eea[2], - attach_req.ue_network_cap.eea[3], - attach_req.ue_network_cap.eea[4], - attach_req.ue_network_cap.eea[5], - attach_req.ue_network_cap.eea[6], - attach_req.ue_network_cap.eea[7]); - m_s1ap_log->console("Attach Request -- UE Network Capabilities EIA: %d%d%d%d%d%d%d%d\n", - attach_req.ue_network_cap.eia[0], - attach_req.ue_network_cap.eia[1], - attach_req.ue_network_cap.eia[2], - attach_req.ue_network_cap.eia[3], - attach_req.ue_network_cap.eia[4], - attach_req.ue_network_cap.eia[5], - attach_req.ue_network_cap.eia[6], - attach_req.ue_network_cap.eia[7]); - m_s1ap_log->console("Attach Request -- MS Network Capabilities Present: %s\n", attach_req.ms_network_cap_present ? "true" : "false"); - m_s1ap_log->console("PDN Connectivity Request -- EPS Bearer Identity requested: %d\n", pdn_con_req.eps_bearer_id); - m_s1ap_log->console("PDN Connectivity Request -- Procedure Transaction Id: %d\n", pdn_con_req.proc_transaction_id); - m_s1ap_log->console("PDN Connectivity Request -- ESM Information Transfer requested: %s\n", pdn_con_req.esm_info_transfer_flag_present ? "true" : "false"); - - //Get Authentication Vectors from HSS - if(!m_hss->gen_auth_info_answer(imsi, ue_ctx_ptr->security_ctxt.k_asme, autn, rand, ue_ctx_ptr->security_ctxt.xres)) - { - m_s1ap_log->console("User not found. IMSI %015lu\n",imsi); - m_s1ap_log->info("User not found. IMSI %015lu\n",imsi); - return false; - } - - //Save UE context - //ue_ctx.imsi = imsi; - if(attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI) - { - //IMSI attach requeires new UE ctxt - ue_ctx.mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id(); - m_s1ap->add_new_ue_ctx(ue_ctx); - } - //Pack NAS Authentication Request in Downlink NAS Transport msg - pack_authentication_request(reply_buffer, ue_ctx_ptr->enb_ue_s1ap_id, ue_ctx_ptr->mme_ue_s1ap_id, autn, rand); - - //Send reply to eNB - *reply_flag = true; - m_s1ap_log->info("Sending Athentication Request\n"); - m_s1ap_log->console("Sending Athentication Request\n"); - //TODO Start T3460 Timer! - */ return true; } @@ -815,57 +686,6 @@ s1ap_nas_transport::handle_tracking_area_update_request(srslte::byte_buffer_t *n /*Packing/Unpacking helper functions*/ -bool -s1ap_nas_transport::unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue, - LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req, - LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req ) -{ - - /*Get NAS Attach Request Message*/ - uint8_t pd, msg_type; - srslte::byte_buffer_t *nas_msg = m_pool->allocate(); - - memcpy(nas_msg->msg, &init_ue->NAS_PDU.buffer, init_ue->NAS_PDU.n_octets); - nas_msg->N_bytes = init_ue->NAS_PDU.n_octets; - liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &pd, &msg_type); - - if(msg_type!=LIBLTE_MME_MSG_TYPE_ATTACH_REQUEST){ - m_s1ap_log->error("Unhandled NAS message within the Initial UE message\n"); - return false; - } - - LIBLTE_ERROR_ENUM err = liblte_mme_unpack_attach_request_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, attach_req); - if(err != LIBLTE_SUCCESS){ - m_s1ap_log->error("Error unpacking NAS attach request. Error: %s\n", liblte_error_text[err]); - return false; - } - /*Log unhandled Attach Request IEs*/ - log_unhandled_attach_request_ies(attach_req); - - /*Get PDN Connectivity Request*/ - err = liblte_mme_unpack_pdn_connectivity_request_msg(&attach_req->esm_msg, pdn_con_req); - if(err != LIBLTE_SUCCESS){ - m_s1ap_log->error("Error unpacking NAS PDN Connectivity Request. Error: %s\n", liblte_error_text[err]); - return false; - } - - if(pdn_con_req->pdn_type == LIBLTE_MME_PDN_TYPE_IPV6) - { - m_s1ap_log->error("PDN Connectivity Request: Only IPv4 connectivity supported.\n"); - return false; - } - if(pdn_con_req->request_type != LIBLTE_MME_REQUEST_TYPE_INITIAL_REQUEST) - { - m_s1ap_log->error("PDN Connectivity Request: Only Initial Request supported.\n"); - return false; - } - /*Log unhandled PDN connectivity request IEs*/ - log_unhandled_pdn_con_request_ies(pdn_con_req); - - m_pool->deallocate(nas_msg); - return true; -} - bool s1ap_nas_transport::pack_authentication_request(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t next_mme_ue_s1ap_id, uint8_t *autn, uint8_t *rand) { From 5ea945d3c52453283be9f669174a73d9d04be023 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 17 Jan 2018 20:03:24 +0000 Subject: [PATCH 161/172] Fixed bug of incrementing UE-MME S1AP twice in GUTI attach. --- srsepc/src/mme/s1ap_nas_transport.cc | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 0277b3763..387481830 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -135,19 +135,15 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA uint32_t enb_ue_s1ap_id = ul_xport->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; uint32_t mme_ue_s1ap_id = ul_xport->MME_UE_S1AP_ID.MME_UE_S1AP_ID; - m_s1ap_log->console("Received Uplink NAS Transport message.\n"); - m_s1ap_log->info("Received Uplink NAS Transport message.\n"); - - ue_ctx_t *ue_ctx = m_s1ap->find_ue_ctx(mme_ue_s1ap_id); if(ue_ctx == NULL) { //TODO UE not registered, send error message. - m_s1ap_log->warning("Could not find UE. MME-UE S1AP id: %lu\n",mme_ue_s1ap_id); + m_s1ap_log->warning("Received uplink NAS, but could not find UE context. MME-UE S1AP id: %lu\n",mme_ue_s1ap_id); return false; } - m_s1ap_log->debug("Found UE. MME-UE S1AP id: %lu\n",mme_ue_s1ap_id); + m_s1ap_log->debug("Received uplink NAS and found UE. MME-UE S1AP id: %lu\n",mme_ue_s1ap_id); //Get NAS message type uint8_t pd, msg_type; @@ -400,7 +396,6 @@ s1ap_nas_transport::handle_nas_guti_attach_request(uint32_t enb_ue_s1ap_id, m_s1ap_log->console("Could not find M-TMSI=0x%x. Sending ID request\n",m_tmsi); m_s1ap_log->info("Could not find M-TMSI=0x%d. Sending Id Request\n", m_tmsi); - ue_ctx.mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id(); m_s1ap->add_new_ue_ctx(ue_ctx); pack_identity_request(reply_buffer, ue_ctx.enb_ue_s1ap_id, ue_ctx.mme_ue_s1ap_id); *reply_flag = true; @@ -625,6 +620,8 @@ s1ap_nas_transport::handle_tracking_area_update_request(srslte::byte_buffer_t *n return false; } */ + m_s1ap_log->console("Warning: Tracking Area Update Request messages not handled yet.\n"); + m_s1ap_log->warning("Warning: Tracking Area Update Request messages not handled yet.\n"); //Setup initiating message LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu; bzero(&tx_pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); From 982fca00fbf00688f79a2977cc1f75a7ca9b1e7d Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 17 Jan 2018 20:47:40 +0000 Subject: [PATCH 162/172] Continuing to cleanup prints. --- srsepc/src/mme/s1ap_nas_transport.cc | 27 ++++++++++++++++++++------- srsepc/src/spgw/spgw.cc | 2 +- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 387481830..00e69104c 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -427,6 +427,17 @@ s1ap_nas_transport::handle_nas_authentication_response(srslte::byte_buffer_t *na LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT auth_resp; bool ue_valid=true; + m_s1ap_log->console("Authentication Response -- IMSI %015lu\n", ue_ctx->imsi); + m_s1ap_log->console("Authentication Response -- RES 0x%x%x%x%x%x%x%x%x\n", + auth_resp.res[0], + auth_resp.res[1], + auth_resp.res[2], + auth_resp.res[3], + auth_resp.res[4], + auth_resp.res[5], + auth_resp.res[6], + auth_resp.res[7] + ); //Get NAS authentication response LIBLTE_ERROR_ENUM err = liblte_mme_unpack_authentication_response_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &auth_resp); if(err != LIBLTE_SUCCESS){ @@ -451,20 +462,22 @@ s1ap_nas_transport::handle_nas_authentication_response(srslte::byte_buffer_t *na } std::cout<console("UE Authentication Rejected. IMSI: %lu\n", ue_ctx->imsi); - m_s1ap_log->warning("UE Authentication Rejected. IMSI: %lu\n", ue_ctx->imsi); + m_s1ap_log->console("UE Authentication Rejected.\n"); + m_s1ap_log->warning("UE Authentication Rejected.\n"); //Send back Athentication Reject pack_authentication_reject(reply_buffer, ue_ctx->enb_ue_s1ap_id, ue_ctx->mme_ue_s1ap_id); *reply_flag = true; + m_s1ap_log->console("Downlink NAS: Sending Authentication Reject.\n"); return false; } else { - m_s1ap_log->console("UE Authentication Accepted. IMSI: %lu\n", ue_ctx->imsi); - m_s1ap_log->info("UE Authentication Accepted. IMSI: %lu\n", ue_ctx->imsi); + m_s1ap_log->console("UE Authentication Accepted.\n"); + m_s1ap_log->info("UE Authentication Accepted.\n"); //Send Security Mode Command pack_security_mode_command(reply_buffer, ue_ctx); *reply_flag = true; + m_s1ap_log->console("Downlink NAS: Sending NAS Security Mode Command.\n"); } return true; } @@ -586,7 +599,7 @@ s1ap_nas_transport::handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_ imsi += id_resp.mobile_id.imsi[i]*std::pow(10,14-i); } m_s1ap_log->info("Id Response -- IMSI: %015lu\n", imsi); - m_s1ap_log->info("Id Response -- IMSI: %015lu\n", imsi); + m_s1ap_log->console("Id Response -- IMSI: %015lu\n", imsi); ue_ctx->imsi = imsi; //Get Authentication Vectors from HSS @@ -602,7 +615,8 @@ s1ap_nas_transport::handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_ //Send reply to eNB *reply_flag = true; - m_s1ap_log->info("DL NAS: Sent Athentication Request\n"); + m_s1ap_log->info("Downlink NAS: Sent Athentication Request\n"); + m_s1ap_log->console("Downlink NAS: Sent Athentication Request\n"); //TODO Start T3460 Timer! return true; @@ -841,7 +855,6 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ue_ctx->enb_ue_s1ap_id; dw_nas->HandoverRestrictionList_present=false; dw_nas->SubscriberProfileIDforRFP_present=false; - m_s1ap_log->console("Sending Security Mode command to MME-UE S1AP Id %d\n", ue_ctx->mme_ue_s1ap_id); //Pack NAS PDU LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT sm_cmd; diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index b39572f11..a5a75dbd3 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -537,7 +537,7 @@ spgw::handle_modify_bearer_request(struct srslte::gtpc_pdu *mb_req_pdu, struct s srslte::gtpc_modify_bearer_response *mb_resp = &mb_resp_pdu->choice.modify_bearer_response; mb_resp->cause.cause_value = srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED; mb_resp->eps_bearer_context_modified.ebi = tunnel_ctx->ebi; - printf("%d %d\n",mb_resp->eps_bearer_context_modified.ebi, tunnel_ctx->ebi); + //printf("%d %d\n",mb_resp->eps_bearer_context_modified.ebi, tunnel_ctx->ebi); mb_resp->eps_bearer_context_modified.cause.cause_value = srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED; } From 1efc4e678ae4d17a7ddcc2176011c75554b09fcf Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 18 Jan 2018 11:25:14 +0100 Subject: [PATCH 163/172] print error msg when UE DB wasn't found --- srsepc/src/hss/hss.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index 659933c7b..b236acc08 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -86,6 +86,7 @@ hss::init(hss_args_t *hss_args, srslte::log_filter *hss_log) /*Read user information from DB*/ if(read_db_file(hss_args->db_file) == false) { + m_hss_log->console("Error reading user database file %s\n", hss_args->db_file.c_str()); return -1; } @@ -140,7 +141,7 @@ hss::read_db_file(std::string db_filename) { return false; } - m_hss_log->info("Opended DB file: %s\n", db_filename.c_str() ); + m_hss_log->info("Opened DB file: %s\n", db_filename.c_str() ); std::string line; while (std::getline(m_db_file, line)) From 8eeaafba5686b370c46add5caebc447e2514b55a Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 18 Jan 2018 11:29:13 +0100 Subject: [PATCH 164/172] fix compiler warning --- srsepc/src/mme/mme_gtpc.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/srsepc/src/mme/mme_gtpc.cc b/srsepc/src/mme/mme_gtpc.cc index a6f09148d..651eb4e49 100644 --- a/srsepc/src/mme/mme_gtpc.cc +++ b/srsepc/src/mme/mme_gtpc.cc @@ -217,7 +217,7 @@ mme_gtpc::send_delete_session_request(ue_ctx_t *ue_ctx) { m_mme_gtpc_log->info("Sending GTP-C Delete Session Request request\n"); srslte::gtpc_pdu del_req_pdu; - srslte::gtpc_f_teid_ie *sgw_ctrl_fteid; + srslte::gtpc_f_teid_ie *sgw_ctrl_fteid = NULL; //FIXME the UE control TEID sould be stored in the UE ctxt, not in the E-RAB ctxt //Maybe a mme_s1ap_id to ctrl teid map as well? @@ -230,6 +230,8 @@ mme_gtpc::send_delete_session_request(ue_ctx_t *ue_ctx) break; } } + //FIXME: add proper error handling + assert(sgw_ctrl_fteid != NULL); srslte::gtpc_header *header = &del_req_pdu.header; header->teid_present = true; From 0d5c110246a02e811377f20156a333d4cf2c39ec Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 18 Jan 2018 11:38:03 +0100 Subject: [PATCH 165/172] specify flags when opening UE db --- srsepc/src/hss/hss.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index b236acc08..0ccea844b 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -136,7 +136,7 @@ hss::set_auth_algo(std::string auth_algo) bool hss::read_db_file(std::string db_filename) { - m_db_file.open(db_filename.c_str()); + m_db_file.open(db_filename.c_str(), std::ifstream::in); if(!m_db_file.is_open()) { return false; From a71edcb8c25bbb682e9bef0ba201cccea4d995c8 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 18 Jan 2018 13:25:33 +0000 Subject: [PATCH 166/172] Continuing to cleanup the prints. --- srsepc/src/main.cc | 2 +- srsepc/src/mme/mme_gtpc.cc | 12 +++++++++--- srsepc/src/mme/s1ap_ctx_mngmt_proc.cc | 2 +- srsepc/src/mme/s1ap_nas_transport.cc | 4 ++-- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index 9d604694a..f70473505 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -257,7 +257,7 @@ level(std::string l) int main (int argc,char * argv[] ) { - cout << "--- Software Radio Systems EPC ---" << endl << endl; + cout << endl <<"--- Software Radio Systems EPC ---" << endl << endl; signal(SIGINT, sig_int_handler); all_args_t args; diff --git a/srsepc/src/mme/mme_gtpc.cc b/srsepc/src/mme/mme_gtpc.cc index a6f09148d..04c175591 100644 --- a/srsepc/src/mme/mme_gtpc.cc +++ b/srsepc/src/mme/mme_gtpc.cc @@ -90,8 +90,8 @@ mme_gtpc::get_new_ctrl_teid() void mme_gtpc::send_create_session_request(uint64_t imsi, uint32_t mme_ue_s1ap_id) { - m_mme_gtpc_log->info("Preparing Create Session Request. IMSI %lu\n", imsi); - m_mme_gtpc_log->console("Preparing Create Session Request. IMSI %lu\n", imsi); + m_mme_gtpc_log->info("Sending Create Session Request.\n"); + m_mme_gtpc_log->console("Sending Create Session Request.\n"); struct srslte::gtpc_pdu cs_req_pdu; struct srslte::gtpc_create_session_request *cs_req = &cs_req_pdu.choice.create_session_request; @@ -115,7 +115,8 @@ mme_gtpc::send_create_session_request(uint64_t imsi, uint32_t mme_ue_s1ap_id) m_mme_gtpc_log->info("Next control TEID: %lu \n", m_next_ctrl_teid); m_mme_gtpc_log->info("Allocated control TEID: %lu \n", cs_req->sender_f_teid.teid); - m_mme_gtpc_log->console("Allocated control TEID: %lu \n", cs_req->sender_f_teid.teid); + m_mme_gtpc_log->console("Creating Session Response -- IMSI: %015lu \n", imsi); + m_mme_gtpc_log->console("Creating Session Response -- MME control TEID: %lu \n", cs_req->sender_f_teid.teid); // APN memcpy(cs_req->apn, "internet", sizeof("internet")); // RAT Type @@ -133,6 +134,7 @@ mme_gtpc::handle_create_session_response(srslte::gtpc_pdu *cs_resp_pdu) { struct srslte::gtpc_create_session_response *cs_resp = & cs_resp_pdu->choice.create_session_response; m_mme_gtpc_log->info("Received Create Session Response\n"); + m_mme_gtpc_log->console("Received Create Session Response\n"); if (cs_resp_pdu->header.type != srslte::GTPC_MSG_TYPE_CREATE_SESSION_RESPONSE) { m_mme_gtpc_log->warning("Could not create GTPC session. Not a create session response\n"); @@ -160,6 +162,10 @@ mme_gtpc::handle_create_session_response(srslte::gtpc_pdu *cs_resp_pdu) sgw_ctrl_fteid.teid = cs_resp_pdu->header.teid; sgw_ctrl_fteid.ipv4 = 0; //FIXME This is not used for now. In the future it will be obtained from the socket addr_info + m_mme_gtpc_log->console("Create Session Response -- SPGW control TEID %d\n", sgw_ctrl_fteid.teid); + in_addr s1u_addr; + s1u_addr.s_addr = cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.ipv4; + m_mme_gtpc_log->console("Create Session Response -- SPGW S1-U Address: %s\n", inet_ntoa(s1u_addr)); m_s1ap->m_s1ap_ctx_mngmt_proc->send_initial_context_setup_request(mme_s1ap_id, cs_resp, sgw_ctrl_fteid); } diff --git a/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc index 8071942bb..7dffe3c35 100644 --- a/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc +++ b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc @@ -200,7 +200,7 @@ s1ap_ctx_mngmt_proc::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, ue_ctx->erabs_ctx[erab_ctxt->e_RAB_ID.E_RAB_ID].sgw_ctrl_fteid.ipv4 = sgw_ctrl_fteid.ipv4; struct in_addr addr; - addr.s_addr = sgw_s1u_ip; + addr.s_addr = htonl(sgw_s1u_ip); m_s1ap_log->info("Sent Intial Context Setup Request. E-RAB id %d \n",erab_ctxt->e_RAB_ID.E_RAB_ID); m_s1ap_log->info("Initial Context -- S1-U TEID 0x%x. IP %s \n", tmp_teid,inet_ntoa(addr)); m_s1ap_log->console("Sent Intial Context Setup Request, E-RAB id %d\n",erab_ctxt->e_RAB_ID.E_RAB_ID); diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 00e69104c..727a8f3a3 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -502,8 +502,8 @@ s1ap_nas_transport::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas m_s1ap_log->warning("IMEI-SV present but not handled"); } - m_s1ap_log->info("Received Security Mode Command Complete. IMSI: %lu\n", ue_ctx->imsi); - m_s1ap_log->console("Received Security Mode Command Complete. IMSI: %lu\n", ue_ctx->imsi); + m_s1ap_log->info("Security Mode Command Complete -- IMSI: %lu\n", ue_ctx->imsi); + m_s1ap_log->console("Security Mode Command Complete -- IMSI: %lu\n", ue_ctx->imsi); if(ue_ctx->eit == true) { pack_esm_information_request(reply_buffer, ue_ctx); From 2dea986acce9e462f8792fa6256c8d48f3a0e37e Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 18 Jan 2018 13:29:29 +0000 Subject: [PATCH 167/172] Sligthly tweaked the ue.conf.example to match the values in the HSS database. --- srsue/ue.conf.example | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index 7c096a268..1fe248850 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -88,9 +88,9 @@ filename = /tmp/ue.log # imei: 15 digit International Mobile Station Equipment Identity ##################################################################### [usim] -algo = milenage +algo = xor op = 63BFA50EE6523365FF14C1F45F88737D -amf = 8000 +amf = 9001 k = 00112233445566778899aabbccddeeff imsi = 001010123456789 imei = 353490069873319 From 11f8cc60adf2fd6243144ae1d012450bec79e117 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 18 Jan 2018 13:39:51 +0000 Subject: [PATCH 168/172] deleted print --- srsepc/src/spgw/spgw.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index a5a75dbd3..2458a065b 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -295,7 +295,7 @@ spgw::run_thread() if (FD_ISSET(m_s1u, &set)) { msg->N_bytes = recvfrom(m_s1u, msg->msg, SRSLTE_MAX_BUFFER_SIZE_BYTES, 0, &src_addr, &addrlen ); - m_spgw_log->console("Received PDU from S1-U. Bytes %d\n", msg->N_bytes); + //m_spgw_log->console("Received PDU from S1-U. Bytes %d\n", msg->N_bytes); //m_spgw_log->debug("Received PDU from S1-U. Bytes %d\n", msg->N_bytes); handle_s1u_pdu(msg); } From 3af13f4f2ea055145d9c8eca0ea75a5786c7ae27 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 18 Jan 2018 13:53:53 +0000 Subject: [PATCH 169/172] Removing docs for now. Information is too basic. --- srsepc/docs/.gitignore | 1 - srsepc/docs/Makefile | 216 --- srsepc/docs/README | 7 - srsepc/docs/source/_imgs/epc-auth-plane.svg | 289 --- .../docs/source/_imgs/epc-control-plane.svg | 598 ------ srsepc/docs/source/_imgs/epc-overall.svg | 381 ---- srsepc/docs/source/_imgs/epc-uml.svg | 1612 ----------------- srsepc/docs/source/_imgs/epc-user-plane.svg | 388 ---- srsepc/docs/source/_static/.gitignore | 0 srsepc/docs/source/_templates/.gitignore | 0 srsepc/docs/source/conf.py | 283 --- srsepc/docs/source/epc_design.rst | 30 - srsepc/docs/source/epc_overview.rst | 225 --- srsepc/docs/source/epc_usage.rst | 2 - srsepc/docs/source/index.rst | 18 - 15 files changed, 4050 deletions(-) delete mode 100644 srsepc/docs/.gitignore delete mode 100644 srsepc/docs/Makefile delete mode 100644 srsepc/docs/README delete mode 100644 srsepc/docs/source/_imgs/epc-auth-plane.svg delete mode 100644 srsepc/docs/source/_imgs/epc-control-plane.svg delete mode 100644 srsepc/docs/source/_imgs/epc-overall.svg delete mode 100644 srsepc/docs/source/_imgs/epc-uml.svg delete mode 100644 srsepc/docs/source/_imgs/epc-user-plane.svg delete mode 100644 srsepc/docs/source/_static/.gitignore delete mode 100644 srsepc/docs/source/_templates/.gitignore delete mode 100644 srsepc/docs/source/conf.py delete mode 100644 srsepc/docs/source/epc_design.rst delete mode 100644 srsepc/docs/source/epc_overview.rst delete mode 100644 srsepc/docs/source/epc_usage.rst delete mode 100644 srsepc/docs/source/index.rst diff --git a/srsepc/docs/.gitignore b/srsepc/docs/.gitignore deleted file mode 100644 index a007feab0..000000000 --- a/srsepc/docs/.gitignore +++ /dev/null @@ -1 +0,0 @@ -build/* diff --git a/srsepc/docs/Makefile b/srsepc/docs/Makefile deleted file mode 100644 index 5dfc21fa8..000000000 --- a/srsepc/docs/Makefile +++ /dev/null @@ -1,216 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = build - -# User-friendly check for sphinx-build -ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) -$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) -endif - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source -# the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source - -.PHONY: help -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " applehelp to make an Apple Help Book" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " texinfo to make Texinfo files" - @echo " info to make Texinfo files and run them through makeinfo" - @echo " gettext to make PO message catalogs" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " xml to make Docutils-native XML files" - @echo " pseudoxml to make pseudoxml-XML files for display purposes" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - @echo " coverage to run coverage check of the documentation (if enabled)" - -.PHONY: clean -clean: - rm -rf $(BUILDDIR)/* - -.PHONY: html -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -.PHONY: dirhtml -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -.PHONY: singlehtml -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -.PHONY: pickle -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -.PHONY: json -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -.PHONY: htmlhelp -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -.PHONY: qthelp -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/srsEPC.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/srsEPC.qhc" - -.PHONY: applehelp -applehelp: - $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp - @echo - @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." - @echo "N.B. You won't be able to view it unless you put it in" \ - "~/Library/Documentation/Help or install it in your application" \ - "bundle." - -.PHONY: devhelp -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/srsEPC" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/srsEPC" - @echo "# devhelp" - -.PHONY: epub -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -.PHONY: latex -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -.PHONY: latexpdf -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -.PHONY: latexpdfja -latexpdfja: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through platex and dvipdfmx..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -.PHONY: text -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -.PHONY: man -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -.PHONY: texinfo -texinfo: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo - @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." - @echo "Run \`make' in that directory to run these through makeinfo" \ - "(use \`make info' here to do that automatically)." - -.PHONY: info -info: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo "Running Texinfo files through makeinfo..." - make -C $(BUILDDIR)/texinfo info - @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." - -.PHONY: gettext -gettext: - $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale - @echo - @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." - -.PHONY: changes -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -.PHONY: linkcheck -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -.PHONY: doctest -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." - -.PHONY: coverage -coverage: - $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage - @echo "Testing of coverage in the sources finished, look at the " \ - "results in $(BUILDDIR)/coverage/python.txt." - -.PHONY: xml -xml: - $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml - @echo - @echo "Build finished. The XML files are in $(BUILDDIR)/xml." - -.PHONY: pseudoxml -pseudoxml: - $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml - @echo - @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/srsepc/docs/README b/srsepc/docs/README deleted file mode 100644 index 7fc58da70..000000000 --- a/srsepc/docs/README +++ /dev/null @@ -1,7 +0,0 @@ -# srsepc-docs -The docs of srsEPC require sphinx, and the sphinx-seqdiag and sphinx-blockdiag extensions. - -On Ubuntu, you can do: -sudo apt install python-sphinx python-sphinxcontrib.seqdiag python-sphinxcontrib.blockdiag - -To make the documentation do 'make html' on the main ./docs folder diff --git a/srsepc/docs/source/_imgs/epc-auth-plane.svg b/srsepc/docs/source/_imgs/epc-auth-plane.svg deleted file mode 100644 index af6426710..000000000 --- a/srsepc/docs/source/_imgs/epc-auth-plane.svg +++ /dev/null @@ -1,289 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - MME - S6a - - HSS - - - - Diameter - - SCTP - - IP - - L2/L1 - - - - - - - Diameter - - SCTP - - IP - - L2/L1 - - - - - diff --git a/srsepc/docs/source/_imgs/epc-control-plane.svg b/srsepc/docs/source/_imgs/epc-control-plane.svg deleted file mode 100644 index 3e84c8a6c..000000000 --- a/srsepc/docs/source/_imgs/epc-control-plane.svg +++ /dev/null @@ -1,598 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - S1-MME - - - S1-APP - - SCTP - - IP - - L2/L1 - - - - S1-APP - - SCTP - - IP - - L2/L1 - - - - eNB - MME - S11 - - - GTP-C - - UDP - - IP - - L2/L1 - - - S-GW - - - - GTP-C - - UDP - - IP - - L2/L1 - - S5/S8 - - - GTP-C - - UDP - - IP - - L2/L1 - - - P-GW - - - - diff --git a/srsepc/docs/source/_imgs/epc-overall.svg b/srsepc/docs/source/_imgs/epc-overall.svg deleted file mode 100644 index 68f037fe7..000000000 --- a/srsepc/docs/source/_imgs/epc-overall.svg +++ /dev/null @@ -1,381 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - LTE - - - - - - - - HSS - - - - P-GW - - - - MME - - - eNB - - - UE - - - - - - - S5/S8 - S1-U - S1-MME - - S6a - S11 - - diff --git a/srsepc/docs/source/_imgs/epc-uml.svg b/srsepc/docs/source/_imgs/epc-uml.svg deleted file mode 100644 index 75aa8aaf0..000000000 --- a/srsepc/docs/source/_imgs/epc-uml.svg +++ /dev/null @@ -1,1612 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/srsepc/docs/source/_imgs/epc-user-plane.svg b/srsepc/docs/source/_imgs/epc-user-plane.svg deleted file mode 100644 index 23d4519ef..000000000 --- a/srsepc/docs/source/_imgs/epc-user-plane.svg +++ /dev/null @@ -1,388 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - S1-U - - - GTP-U - - UDP - - IP - - L2/L1 - - - - GTP-U - - UDP - - IP - - L2/L1 - - - - eNB - S-GW - S5/S8 - - - GTP-U - - UDP - - IP - - L2/L1 - - - P-GW - - - diff --git a/srsepc/docs/source/_static/.gitignore b/srsepc/docs/source/_static/.gitignore deleted file mode 100644 index e69de29bb..000000000 diff --git a/srsepc/docs/source/_templates/.gitignore b/srsepc/docs/source/_templates/.gitignore deleted file mode 100644 index e69de29bb..000000000 diff --git a/srsepc/docs/source/conf.py b/srsepc/docs/source/conf.py deleted file mode 100644 index 1855f653f..000000000 --- a/srsepc/docs/source/conf.py +++ /dev/null @@ -1,283 +0,0 @@ -# -*- coding: utf-8 -*- -# -# srsEPC documentation build configuration file, created by -# sphinx-quickstart on Mon Oct 2 14:30:47 2017. -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys -import os - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = ['sphinxcontrib.seqdiag','sphinxcontrib.blockdiag'] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# source_suffix = ['.rst', '.md'] -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'srsEPC' -copyright = u'2017, Pedro Alvarez' -author = u'Pedro Alvarez' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = u'2.0.0' -# The full version, including alpha/beta/rc tags. -release = u'2.0.0' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = [] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = False - - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'alabaster' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -html_theme_options = {"nosidebar": "true"} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (relative to this directory) to use as a favicon of -# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -#html_extra_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_domain_indices = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None - -# Language to be used for generating the HTML full-text search index. -# Sphinx supports the following languages: -# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' -# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' -#html_search_language = 'en' - -# A dictionary with options for the search language support, empty by default. -# Now only 'ja' uses this config value -#html_search_options = {'type': 'default'} - -# The name of a javascript file (relative to the configuration directory) that -# implements a search results scorer. If empty, the default will be used. -#html_search_scorer = 'scorer.js' - -# Output file base name for HTML help builder. -htmlhelp_basename = 'srsEPCdoc' - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', - -# Latex figure (float) alignment -#'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - (master_doc, 'srsEPC.tex', u'srsEPC Documentation', - u'Pedro Alvarez', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# If true, show page references after internal links. -#latex_show_pagerefs = False - -# If true, show URL addresses after external links. -#latex_show_urls = False - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_domain_indices = True - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'srsepc', u'srsEPC Documentation', - [author], 1) -] - -# If true, show URL addresses after external links. -#man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - (master_doc, 'srsEPC', u'srsEPC Documentation', - author, 'srsEPC', 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -#texinfo_appendices = [] - -# If false, no module index is generated. -#texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False diff --git a/srsepc/docs/source/epc_design.rst b/srsepc/docs/source/epc_design.rst deleted file mode 100644 index 17861938f..000000000 --- a/srsepc/docs/source/epc_design.rst +++ /dev/null @@ -1,30 +0,0 @@ -EPC Design -========== - -Code Structure -************** - -The LTE library should include the following functionality that will be common accress multiple nodes. - -.. _epc-overall: - -.. figure:: _imgs/epc-uml.svg - - EPC overall class architecture - - - - -MME Design -********** - -The srsMME must maintain three EPC interfaces, the S1-MME, the S11 and the S6a interfaces. The S1-MME will use an SCTP (many-to-one) socket and the S11 will use the GTP-Cv2 protocol over UDP. The S6a will be implmented as a Diameter application over UDP. - -The main loop of the MME will - -HSS Design -********** - -SP-GW Design -*********** - diff --git a/srsepc/docs/source/epc_overview.rst b/srsepc/docs/source/epc_overview.rst deleted file mode 100644 index 40309eee5..000000000 --- a/srsepc/docs/source/epc_overview.rst +++ /dev/null @@ -1,225 +0,0 @@ -EPC Overview -============ - -The Evolved Packet Core (EPC) refers to the elements of an LTE network that make up the core of the network. The main functionality of these elements is to provide data conectivity, mobility and user authentification. - -:ref:`epc-overall` illustrates the main components and their interfaces in the EPC. - -.. _epc-overall: - -.. figure:: _imgs/epc-overall.svg - - EPC overall architecture - -* *HSS*: The Home Subscriber Service (HSS) is the user database. It stores information such as the user's id, key, usage limits, etc. It is responsible for authenticating an authorizing the user's access to the network. - -* *MME*: Mobility Managment Entity (MME) is the main control element in the network. It handles mobility and attach control messages. It is also responsible for paging UEs in idle mode. - -* *S-GW*: The S-GW is the main dataplane gateway for the users, as it provides the mobility anchor for the UEs. It works as an IP router and helps setting up GTP sessions between the eNB and the P-GW. - -* *P-GW*: The Packet Gateway (P-GW) is the point of contact with external networks. It enforces the QoS parameters for subscriber sessions. - -EPC User and Control Plane -************************** - -In this subsection, we will breifly describe the EPC's user and control plane. The user plane, uses the GPRS Tunneling Protocol to estabilish tunnels between the P-GW and the eNB. The GTP is a IP-over-IP protocol, that encapsulates user packets in another IP packet plus a label to provide mobility. To see a more detailed description of GTP, go to :ref:`gtp-section`. - -These user plane tunnels are set up between the eNB, the S-GW and the P-GW over the S1-U and S5/S8 interfaces. The full protocol stack is illustrated in :ref:`epc-user-plane`. - -.. _epc-user-plane: - -.. figure:: _imgs/epc-user-plane.svg - - EPC User Plane (S1-U and S5/S8) - -To establish these user tunnels, the GTP-Cv2 protocol and the S1-APP protocol are used. These protocols provide the interfaces between the eNB, the MME, the S-PGW and the P-GW. The full protocol stack can be seen in :ref:`epc-control-plane`. The details of the GTP-Cv2 and S1-APP can be seen in :ref:`gtp-section` and :ref:`s1app-section`, respectively. - -.. _epc-control-plane: - -.. figure:: _imgs/epc-control-plane.svg - - EPC Control Plane (S1-MME, S11 and S5/S8) - -Finally, to authenticate the user and authorize him or her, the MME comunicates with the HSS over the S6a interface. This interface will run the Diameter protocol the exchange user authentification and authorization information, as seen in :ref:`epc-auth-plane`. More details on :ref:`diameter-section` - -.. _epc-auth-plane: - -.. figure:: _imgs/epc-auth-plane.svg - - EPC Authentication Plane (S6a) - -Procedures -********** - -In this section we will generally describe the most relevant procedures and their implementation status. This will be more of an higher layer view, as the details of each message passed will be elaborated on the :ref:`s1app-section`, :ref:`gtp-section` and :ref:`diameter-section` sections. - -UE Attach proceedure -++++++++++++++++++++ - -The UE attach procedure is one of the first and most crucial steps for the UE to get connectivity. For this reason, this is the first procedure to be described. This can be broken down to multiple procedures and you can see bellow - -.. seqdiag:: - - seqdiag { - - === Random Access Procedure === - UE <- eNB [label = "MIB"] - UE <- eNB [label = "SIB1"] - UE <- eNB [label = "SIB2"] - UE -> eNB [label = "Random Access Preamble"]; - UE <- eNB [label = "Random Access Response [Tmp C-RNTI]"]; - UE -> eNB [label = "RRC Connection Request [Tmp C-RNTI]"]; - UE <- eNB [label = "RRC Connection Setup [C-RNTI]"]; - UE -> eNB [label = "RRC Connection Completed [Attach Request (IMSI), PDN Connection Request]"]; - === User Authentication Procedure === - eNB -> MME [label = "Initial UE Msg [Attach Request, PDN Connection Request]"]; - MME -> HSS [label = "Auth Info Request (IMSI)"]; - MME <- HSS [label = "Auth Info Answer (Kasme, AUTN, RAND, XRES)"] - eNB <- MME [label = "DL NAS Xport [Authn Request]"]; - UE <- eNB [label = "DL Info Xfer [Auth Request (AUTN, RAND)]"]; - UE -> eNB [label = "Auth Response (RES)"]; - eNB -> MME [label = "Auth Response (RES)", note = "MME compares RES with XRES"]; - === NAS Security Setup Procedure === - eNB <- MME [label = "DL NAS Xport [Security Mode Command]"]; - UE <- eNB [label = "DL Info Xfer [Security Mode Command]"]; - UE -> eNB [label = "Security Mode Complete"] - eNB -> MME [label = "SMC Completed"] - === Authorization === - MME -> HSS [label = "Location Update Request (IMSI)"] - MME <- HSS [label = "Location Update Response (Subscription Data)"] - === GTP Tunnel setup === - MME -> SGW [label = "Create Session Request (IMSI, TEID, PGW IP)"] - SGW -> PGW [label = "Create Session Request (IMSI, TEID)"] - SGW <- PGW [label = "Create Session Response (TEIDs)", note = "S5 GTP Tunnel created"] - MME <- SGW [label = "Create Session Response (TEIDs)"] - eNB <- MME [label = "Initial Context Setup Request (UE Context Info, TEID)", note="NAS Attach Accept, NAS Activate default bearer"] - UE <- eNB [label = "RRC Security Mode Command (AS Algorithm)"] - UE -> eNB [label = "RRC Security Mode Complete"] - //UE <-> eNB [label = "UE Radio Capabilities"] - UE <- eNB [label = "RRC Connection Reconfiguration", note = "NAS Attach Accept, NAS Activate Default Bearer"] - UE -> eNB [label = "RRC Reconfiguration Complete"] - eNB -> MME [label = "Initial Context Setup Complete (S1U TIED)"] - UE -> eNB [label = "Uplink Information Transfer [NAS Attach Complete, NAS Activate default bearer accept]"] - eNB -> MME [label = "Uplink NAS Xport [NAS Attach Complete, NAS Activate default bearer accept]"] - MME -> SGW [label = "Modify bearer request (S1-U TEID)"] - MME <- SGW [label = "Modify bearer response"] - === Networking Setup === - } - -.. _gtp-section: - -GPRS Tunneling Protocol -*********************** - -The GPRS Tunneling Protocol (GTP) main objective is to tunnel IP packets to the UE, allowing him to keep his IP even when the user is mobile. -It is composed of two parts, the user plane and the control plane. - -Transport Layer -+++++++++++++++ - -Both GTP-C and GTP-U use UDP for the transport layer. The specific port for GTP-C TX and RX is 2123. For GTP-U packets must have a destination port of 2152, but can use any source port. - -Setting up TEIDs -++++++++++++++++ - -In this section we will describe the setup of GTP tunnels, both between the S-GW and P-GW and between the S-GW and the eNB. -We will start with the setup of the of GTP tunnels between the S-GW and the P-GW for simplicity. - -Initially, the S-GW sends a message to TEID 0 (the butler tunnel) saying that it wants to set up a GTP-U tunnel. This should include the IMSI of the user, the IP address of the S-GW, control plane TEID_sgw_d, user plane TEID_sgw_d, - -The P-GW replies with the with the Create Session Response message, that contains the control TEID_pgw_u that the P-GW allocated for signaling messages for that UE. It will also send the P-GWs IP address and user TEID_pgw_u for uplink user traffic. After this, the TEID tunnels are set up between the S-GW and the P-GW. - -For the set up of GTP-U tunnels between the eNB and the S-GW the process is similar, but the S1-MME (which uses S1-APP instead of GTP-C) must be used. This procedure is initiated by the MME requesting a GTP-U tunnel on behalf of the eNB, by sending a Create Session Request to the S-GW. The S-GW will create a tunnel between himself and the P-GW and after that it will reply to the MME. The MME will finally relay the information of the IP of the S-GW and the TEIDs to the eNB in the Initial Context Setup Request message. - -The whole process is illustrated below: - -.. seqdiag:: - - seqdiag { - activation = none; - MME -> S-GW [label = "Create Session Request"]; - S-GW -> P-GW [label = "Create Session Request"] - S-GW <- P-GW [label = "Create Session Response"]; - MME <- S-GW [label = "Create Session Response"]; - eNB <- MME [label = "Initial Context Setup"]; - } - - - -.. _s1app-section: - -S1-APP -****** - -In this section, we will describe the S1-APP protocol. The S1-APP will run over SCTP and the eNB will initiate the assotiation using the destination port 36412. - -This protocol involved in of multiple procedures, such as S1-MME Setup, UE attach, paging etc. -As this protocol is quite large, we will focus on the procedures we consider most relevant. - -The following sub-sections describe these procedures and give some small indication of their implementation status: - -* :ref:`s1-setup` -* :ref:`erab-setup-request` - -.. _s1-setup: - -S1 Setup -++++++++++ - -This is the first procedure between the eNB and the MME, started once the transport layer is active, to setup the S1-MME connection. -After this procedure takes place, both nodes will store the information exchanged. If the information is already present, it is erased and updated with the most recent information exchanged. - -In this procedure, the following information is sent to the MME from the eNB: - -* *eNB Id* (M): This field will be the global eNB Id; -* *eNB Name* (O): This field will include the human readable name of the eNB; -* *Supported TA* (M): This field will include the -* *Default Paging DRX* (M): This message -* *CSG List Ids* (O): This - -In the case of success, the MME will reply the following: - -* *MME Name* (O): This message will include the human readable name of the MME; -* *Served GUMMEI* (M): This field will contain the Globally Unique MME Id. This is composed by the MCC, MNC, MME Group Id and MME code. -* *Relative MME Capacity* (M): This message will contain a weight factor for MME load balancing purposes -* *Criticality Diagnosis* (O): This field indicates if some IE were not understood by the MME or missing - -In the case of failure, the MME will reply the following: - -* *Cause Id* (M): This message will what was the cause for the setup failure; -* *Time to wait* (O): This will indicate the eNB to wait at least the indicated amount of time before restarting the S1 Setup -* *Criticality Diagnosis* (O): This field indicates if some IE were not understood by the MME or missing - -You can see the message diagram for both the success and failure case below: - -.. _success-s1-setup: - -.. seqdiag:: - - seqdiag { - activation = none; - eNB -> MME [label = "S1 Setup Request"]; - eNB <- MME [label = "S1 Setup Response"]; - } - -.. _fail-s1-setup: - -.. seqdiag:: - - seqdiag { - activation = none; - eNB -> MME [label = "S1 Setup Request"] - eNB <- MME [label = "S1 Setup Failure"] - } - - -.. _erab-setup-request: - -E-RAB Setup Request -+++++++++++++++++++ - -.. _diameter-section: - -Diameter -******** - diff --git a/srsepc/docs/source/epc_usage.rst b/srsepc/docs/source/epc_usage.rst deleted file mode 100644 index e98ac2cfa..000000000 --- a/srsepc/docs/source/epc_usage.rst +++ /dev/null @@ -1,2 +0,0 @@ -EPC Usage -********* diff --git a/srsepc/docs/source/index.rst b/srsepc/docs/source/index.rst deleted file mode 100644 index 4cacb24ed..000000000 --- a/srsepc/docs/source/index.rst +++ /dev/null @@ -1,18 +0,0 @@ - -.. srsEPC documentation master file, created by - sphinx-quickstart on Mon Oct 2 14:30:47 2017. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to srsEPC's documentation! -================================== - - -.. toctree:: - :maxdepth: 2 - - epc_overview.rst - epc_design.rst - epc_usage.rst - - From 6945ac697c0bc9bc1cf9f008996d5b3e457e24a2 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 18 Jan 2018 14:10:15 +0000 Subject: [PATCH 170/172] Added command commandline argument to the interface masquerading script --- srsepc/if_masq.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/srsepc/if_masq.sh b/srsepc/if_masq.sh index ee6c41392..88d7f370a 100755 --- a/srsepc/if_masq.sh +++ b/srsepc/if_masq.sh @@ -23,8 +23,15 @@ #Check for sudo rights sudo -v || exit -echo "Masquerading Interface" +#Check if outbound interface was specified +if [ ! $# -eq 1 ] + then + echo "Usage :'sudo ./if_masq.sh ' " + exit +fi + +echo "Masquerading Interface "$1 echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward 1>/dev/null -sudo iptables -t nat -A POSTROUTING -o wlp58s0 -j MASQUERADE +sudo iptables -t nat -A POSTROUTING -o $1 -j MASQUERADE From b04d49abd3abc625cc117d04cb1ad6bc6e832c11 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 18 Jan 2018 16:56:31 +0100 Subject: [PATCH 171/172] fix logging --- srsepc/src/hss/hss.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index 0ccea844b..e421819b6 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -151,7 +151,7 @@ hss::read_db_file(std::string db_filename) std::vector split = split_string(line,','); if(split.size()!=5) { - m_hss_log->error("Error parsing .csv file %d\n"); + m_hss_log->error("Error parsing UE database\n"); return false; } hss_ue_ctx_t *ue_ctx = new hss_ue_ctx_t; From bb4a06e7366b892479e21c378051ac96b247fb4d Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 18 Jan 2018 17:18:48 +0000 Subject: [PATCH 172/172] Fixed some hard-coded values. --- srsepc/src/mme/s1ap_nas_transport.cc | 47 ++++++++++++++++------------ 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 727a8f3a3..8eb0f21ea 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -1002,6 +1002,27 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE m_s1ap_log->info("Packing Attach Accept\n"); + //Get decimal MCC and MNC + uint32_t mcc = 0; + mcc += 0x000F & m_s1ap->m_s1ap_args.mcc; + mcc += 10*( (0x00F0 & m_s1ap->m_s1ap_args.mcc) >> 4); + mcc += 100*( (0x0F00 & m_s1ap->m_s1ap_args.mcc) >> 8); + + uint32_t mnc = 0; + if( 0xFF00 == (m_s1ap->m_s1ap_args.mnc & 0xFF00 )) + { + //Two digit MNC + mnc += 0x000F & m_s1ap->m_s1ap_args.mnc; + mnc += 10*((0x00F0 & m_s1ap->m_s1ap_args.mnc) >> 4); + } + else + { + //Three digit MNC + mnc += 0x000F & m_s1ap->m_s1ap_args.mnc; + mnc += 10*((0x00F0 & m_s1ap->m_s1ap_args.mnc) >> 4); + mnc += 100*((0x0F00 & m_s1ap->m_s1ap_args.mnc) >> 8); + } + //Attach accept attach_accept.eps_attach_result = LIBLTE_MME_EPS_ATTACH_RESULT_EPS_ONLY; //Mandatory @@ -1010,17 +1031,17 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE attach_accept.t3412.value = 30; // 30 minute periodic timer //FIXME: Set tai_list from config attach_accept.tai_list.N_tais = 1; - attach_accept.tai_list.tai[0].mcc = 1;//m_s1ap->m_s1ap_args.mcc; - attach_accept.tai_list.tai[0].mnc = 1;//m_s1ap->m_s1ap_args.mnc; + attach_accept.tai_list.tai[0].mcc = mcc; + attach_accept.tai_list.tai[0].mnc = mnc; attach_accept.tai_list.tai[0].tac = m_s1ap->m_s1ap_args.tac; //Allocate a GUTI ot the UE attach_accept.guti_present=true; attach_accept.guti.type_of_id = 6; //110 -> GUTI - attach_accept.guti.guti.mcc = 1;//m_s1ap->m_s1ap_args.mcc; - attach_accept.guti.guti.mnc = 1;//m_s1ap->m_s1ap_args.mnc; - attach_accept.guti.guti.mme_group_id = 0x0001; - attach_accept.guti.guti.mme_code = 0xa1; + attach_accept.guti.guti.mcc = mcc; + attach_accept.guti.guti.mnc = mnc; + attach_accept.guti.guti.mme_group_id = m_s1ap->m_s1ap_args.mme_group; + attach_accept.guti.guti.mme_code = m_s1ap->m_s1ap_args.mme_code; attach_accept.guti.guti.m_tmsi = m_s1ap->allocate_m_tmsi(ue_ctx->mme_ue_s1ap_id); m_s1ap_log->debug("Allocated GUTI: MCC %d, MNC %d, MME Group Id %d, MME Code 0x%x, M-TMSI 0x%x\n", attach_accept.guti.guti.mcc, @@ -1028,20 +1049,6 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE attach_accept.guti.guti.mme_group_id, attach_accept.guti.guti.mme_code, attach_accept.guti.guti.m_tmsi); - /* - typedef struct{ - uint32 m_tmsi; - uint16 mcc; - uint16 mnc; - uint16 mme_group_id; - uint8 mme_code; - }LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT; - typedef struct{ - LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti; - uint8 type_of_id; - uint8 imsi[15]; - uint8 imei[15]; - }LIBLTE_MME_EPS_MOBILE_ID_STRUCT;*/ //Make sure all unused options are set to false attach_accept.lai_present=false;