diff --git a/CMakeLists.txt b/CMakeLists.txt index fad9252d1..0788ec335 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,8 +68,10 @@ option(ENABLE_SRSEPC "Build srsEPC application" ON) option(DISABLE_SIMD "disable simd instructions" OFF) option(ENABLE_GUI "Enable GUI (using srsGUI)" ON) +option(ENABLE_UHD "Enable UHD" ON) option(ENABLE_BLADERF "Enable BladeRF" ON) option(ENABLE_SOAPYSDR "Enable SoapySDR" ON) +option(ENABLE_HARDSIM "Enable support for SIM cards" ON) option(BUILD_STATIC "Attempt to statically link external deps" OFF) option(RPATH "Enable RPATH" OFF) @@ -133,21 +135,25 @@ else(POLARSSL_FOUND) endif(POLARSSL_FOUND) # Hard-SIM support -find_package(PCSCLite) -if (PCSCLITE_FOUND) - message(STATUS "Building with PCSC support.") - add_definitions(-DHAVE_PCSC) - set(HAVE_PCSC TRUE) - include_directories(${PCSCLITE_INCLUDE_DIR}) - #link_directories(${PCSCLITE_LIBRARIES}) -endif (PCSCLITE_FOUND) +if(ENABLE_HARDSIM) + find_package(PCSCLite) + if (PCSCLITE_FOUND) + message(STATUS "Building with PCSC support.") + add_definitions(-DHAVE_PCSC) + set(HAVE_PCSC TRUE) + include_directories(${PCSCLITE_INCLUDE_DIR}) + #link_directories(${PCSCLITE_LIBRARIES}) + endif (PCSCLITE_FOUND) +endif(ENABLE_HARDSIM) # UHD -find_package(UHD) -if(UHD_FOUND) - include_directories(${UHD_INCLUDE_DIRS}) - link_directories(${UHD_LIBRARY_DIRS}) -endif(UHD_FOUND) +if(ENABLE_UHD) + find_package(UHD) + if(UHD_FOUND) + include_directories(${UHD_INCLUDE_DIRS}) + link_directories(${UHD_LIBRARY_DIRS}) + endif(UHD_FOUND) +endif(ENABLE_UHD) # BladeRF if(ENABLE_BLADERF) diff --git a/README.md b/README.md index 88f2d5ebe..c20cba960 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,11 @@ For example, on Ubuntu 17.04, one can install the required libraries with: ``` sudo apt-get install cmake libfftw3-dev libmbedtls-dev libboost-program-options-dev libconfig++-dev libsctp-dev ``` +or on Fedora: +``` +dnf install cmake fftw3-devel polarssl-devel lksctp-tools-devel libconfig-devel boost-devel +``` + Note that depending on your flavor and version of Linux, the actual package names may be different. * Optional requirements: diff --git a/debian/config b/debian/config new file mode 100755 index 000000000..83d7550e1 --- /dev/null +++ b/debian/config @@ -0,0 +1,13 @@ +#!/bin/sh + +# Exit on error +set -e + +# Source debconf library. +. /usr/share/debconf/confmodule + +# Ask questions +db_input low srslte/install_configs_question || true + +# Show interface +db_go || true diff --git a/debian/control b/debian/control index 58720070f..a20f8df6f 100644 --- a/debian/control +++ b/debian/control @@ -1,14 +1,36 @@ Source: srslte -Section: misc +Section: universe/misc Priority: optional Maintainer: Andre Puschmann -Build-Depends: debhelper (>= 9), dh-exec, cmake, build-essential, libfftw3-dev, libmbedtls-dev, libboost-program-options-dev, libconfig++-dev, libsctp-dev, libuhd-dev, uhd-host +Build-Depends: + debhelper (>= 9), + dh-exec, + cmake, + build-essential, + libfftw3-dev, + libmbedtls-dev, + libboost-program-options-dev, + libconfig++-dev, + libsctp-dev, + libuhd-dev, + uhd-host Standards-Version: 4.1.1 -Homepage: https://github.com/srsLTE/srsLTE/ +Homepage: http://www.softwareradiosystems.com +Vcs-Git: https://github.com/srsLTE/srsLTE.git +Vcs-Browser: https://github.com/srsLTE/srsLTE/ Package: srslte Architecture: any -Depends: libfftw3-3 (>= 3.3.3-1), libboost-program-options1.62.0 (>= 1.62.0), libmbedcrypto1 (>= 2.8.0-1), libconfig++9v5 (>= 1.5-0.2), libsctp1 (>= 1.0.16+dfsg-3), uhd-host (>= 3.9.2-1), libuhd003.010.003 (>= 3.10.3.0-2) +Depends: + libfftw3-3 (>= 3.3.3-1), + libboost-program-options1.62.0 (>= 1.62.0), + libmbedcrypto1 (>= 2.8.0-1), + libconfig++9v5 (>= 1.5-0.2), + libsctp1 (>= 1.0.16+dfsg-3), + uhd-host (>= 3.9.2-1), + libuhd003.010.003 (>= 3.10.3.0-2), + ${shlibs:Depends}, + ${misc:Depends} Description: This is srsLTE, a free and open-source LTE software suite. This software allows you to run a full end-to-end, open-source LTE system. It contains a UE, eNB and EPC implementation. diff --git a/debian/copyright b/debian/copyright index 592199877..62356443a 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,516 +1,81 @@ -Copyright (C) 2013-2016 Software Radio Systems Limited. All rights reserved. - -The following copyright notices are for libraries used within srsLTE: - ------------------------------------------------------------ -FEC Library - Version 3.0.1 - August 7th, 2007 ------------------------------------------------------------ - -COPYRIGHT - -This package is copyright 2006 by Phil Karn, KA9Q. It may be used -under the terms of the GNU Lesser General Public License (LGPL). - - -GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: srsLTE +Upstream-Contact: srsLTE packaging team +License: AGPL-3+ +Copyright: 2013-2018, Software Radio Systems Limited. +Source: https://www.github.com/srsLTE + +Files: * +Copyright: 2013-2018, Software Radio Systems Limited. +License: AGPL-3+ + +Files: lib/src/phy/fec/viterbi37_port.c + lib/src/phy/fec/viterbi37_sse.c + lib/src/phy/fec/parity.c +Copyright: 2009, Phil Karn, KA9Q +License: LGPL-2.1 + +Files: srsue/src/upper/pcsc_usim.cc + srsue/hdr/upper/pcsc_usim.h +Copyright: 2002-2014, Jouni Malinen +License: BSD-3-clause + + +License: AGPL-3+ + This program 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. + . + This program 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. + . + On Debian systems, the complete text of the AGPL 3 can be found in + /usr/share/doc/srslte/LICENSE + + +License: LGPL-2.1 + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + . + This library 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 + Lesser General Public License for more details. + . + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +License: BSD-3-clause + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + . + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + . + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + . + 3. Neither the name(s) of the above-listed copyright holder(s) nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + . + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/debian/postinst b/debian/postinst new file mode 100755 index 000000000..2009e6847 --- /dev/null +++ b/debian/postinst @@ -0,0 +1,14 @@ +#!/bin/bash + +# Source debconf library. +. /usr/share/debconf/confmodule + +# Fetching configuration from debconf +db_get srslte/install_configs_question +ANSWER1=$RET + +if [ $ANSWER1 == "true" ]; then + srslte_install_configs.sh +fi + +#DEBHELPER# diff --git a/debian/srslte.install b/debian/srslte.install deleted file mode 100755 index 7ed295542..000000000 --- a/debian/srslte.install +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/dh-exec -srsue/ue.conf.example => usr/share/srslte/config/ue.conf -srsenb/enb.conf.example => usr/share/srslte/config/enb.conf -srsenb/rr.conf.example => usr/share/srslte/config/rr.conf -srsenb/drb.conf.example => usr/share/srslte/config/drb.conf -srsenb/sib.conf.example => usr/share/srslte/config/sib.conf -srsepc/epc.conf.example => usr/share/srslte/config/epc.conf -srsepc/mbms.conf.example => usr/share/srslte/config/mbms.conf -srsepc/user_db.csv.example => usr/share/srslte/config/user_db.csv diff --git a/debian/templates b/debian/templates new file mode 100644 index 000000000..97127f51a --- /dev/null +++ b/debian/templates @@ -0,0 +1,6 @@ +Template: srslte/install_configs_question +Type: boolean +Default: true +Description: Install configs? + This installs the default srsLTE configuration files to the user's + home directory (~/.srs) but keeps any existing config files. diff --git a/lib/include/srslte/asn1/liblte_mme.h b/lib/include/srslte/asn1/liblte_mme.h index 3d9640806..144c188fc 100644 --- a/lib/include/srslte/asn1/liblte_mme.h +++ b/lib/include/srslte/asn1/liblte_mme.h @@ -2814,6 +2814,8 @@ typedef struct{ }LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT; // Functions LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_response_msg(LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT *auth_resp, + uint8 sec_hdr_type, + uint32 count, LIBLTE_BYTE_MSG_STRUCT *msg); LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_response_msg(LIBLTE_BYTE_MSG_STRUCT *msg, LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT *auth_resp); diff --git a/lib/include/srslte/common/buffer_pool.h b/lib/include/srslte/common/buffer_pool.h index 75c56fc0e..0a87c0df1 100644 --- a/lib/include/srslte/common/buffer_pool.h +++ b/lib/include/srslte/common/buffer_pool.h @@ -183,7 +183,7 @@ public: } b->reset(); if (!pool->deallocate(b)) { - fprintf(stderr, "Error deallocating PDU: Addr=0x%lx not found in pool\n", (uint64_t) b); + printf("Error deallocating PDU: Addr=0x%lx not found in pool\n", (uint64_t) b); } b = NULL; } diff --git a/lib/include/srslte/common/pcap.h b/lib/include/srslte/common/pcap.h index 18b66a141..0f63ff11d 100644 --- a/lib/include/srslte/common/pcap.h +++ b/lib/include/srslte/common/pcap.h @@ -35,7 +35,7 @@ #define MAC_LTE_DLT 147 #define NAS_LTE_DLT 148 #define RLC_LTE_DLT 149 // UDP needs to be selected as protocol - +#define S1AP_LTE_DLT 150 /* This structure gets written to the start of the file */ typedef struct pcap_hdr_s { @@ -165,6 +165,10 @@ typedef struct { #define RLC_LTE_PAYLOAD_TAG 0x01 +/* Context information for every S1AP PDU that will be logged */ +typedef struct S1AP_Context_Info_s { + // No Context yet +} S1AP_Context_Info_t; /************************************************************************** * API functions for opening/closing LTE PCAP files * @@ -398,4 +402,37 @@ inline int LTE_PCAP_RLC_WritePDU(FILE *fd, RLC_Context_Info_t *context, return 1; } +/************************************************************************** + * API functions for writing S1AP PCAP files * + **************************************************************************/ + +/* Write an individual PDU (PCAP packet header + s1ap-context + s1ap-pdu) */ +inline int LTE_PCAP_S1AP_WritePDU(FILE *fd, S1AP_Context_Info_t *context, + const unsigned char *PDU, unsigned int length) +{ + pcaprec_hdr_t packet_header; + + /* Can't write if file wasn't successfully opened */ + if (fd == NULL) { + printf("Error: Can't write to empty file handle\n"); + return 0; + } + + /****************************************************************/ + /* PCAP Header */ + struct timeval t; + gettimeofday(&t, NULL); + packet_header.ts_sec = t.tv_sec; + packet_header.ts_usec = t.tv_usec; + packet_header.incl_len = length; + packet_header.orig_len = length; + + /***************************************************************/ + /* Now write everything to the file */ + fwrite(&packet_header, sizeof(pcaprec_hdr_t), 1, fd); + fwrite(PDU, 1, length, fd); + + return 1; +} + #endif // SRSLTE_PCAP_H diff --git a/lib/include/srslte/common/s1ap_pcap.h b/lib/include/srslte/common/s1ap_pcap.h new file mode 100644 index 000000000..b00d44394 --- /dev/null +++ b/lib/include/srslte/common/s1ap_pcap.h @@ -0,0 +1,23 @@ +#ifndef SRSLTE_S1AP_PCAP_H +#define SRSLTE_S1AP_PCAP_H + +#include "srslte/common/pcap.h" + +namespace srslte { + +class s1ap_pcap +{ +public: + s1ap_pcap() {enable_write=false; pcap_file = NULL; } + void enable(); + void open(const char *filename); + void close(); + void write_s1ap(uint8_t *pdu, uint32_t pdu_len_bytes); +private: + bool enable_write; + FILE *pcap_file; +}; + +} //namespace srslte + +#endif // SRSLTE_NAS_PCAP_H diff --git a/lib/include/srslte/upper/rlc_common.h b/lib/include/srslte/upper/rlc_common.h index a5b2e0403..c9655efae 100644 --- a/lib/include/srslte/upper/rlc_common.h +++ b/lib/include/srslte/upper/rlc_common.h @@ -163,6 +163,7 @@ public: srslte::mac_interface_timers *mac_timers_) = 0; virtual void configure(srslte_rlc_config_t cnfg) = 0; virtual void stop() = 0; + virtual void reestablish() = 0; virtual void empty_queue() = 0; virtual rlc_mode_t get_mode() = 0; diff --git a/lib/include/srslte/upper/rlc_tm.h b/lib/include/srslte/upper/rlc_tm.h index 774011292..d78ab59c4 100644 --- a/lib/include/srslte/upper/rlc_tm.h +++ b/lib/include/srslte/upper/rlc_tm.h @@ -49,6 +49,7 @@ public: mac_interface_timers *mac_timers); void configure(srslte_rlc_config_t cnfg); void stop(); + void reestablish(); void empty_queue(); rlc_mode_t get_mode(); diff --git a/lib/include/srslte/upper/rlc_um.h b/lib/include/srslte/upper/rlc_um.h index 864edaded..f099f60cf 100644 --- a/lib/include/srslte/upper/rlc_um.h +++ b/lib/include/srslte/upper/rlc_um.h @@ -57,6 +57,7 @@ public: srsue::rrc_interface_rlc *rrc_, mac_interface_timers *mac_timers_); void configure(srslte_rlc_config_t cnfg); + void reestablish(); void stop(); void empty_queue(); bool is_mrb(); diff --git a/lib/src/asn1/liblte_mme.cc b/lib/src/asn1/liblte_mme.cc index 189f9138a..5cb00e5cb 100644 --- a/lib/src/asn1/liblte_mme.cc +++ b/lib/src/asn1/liblte_mme.cc @@ -6180,6 +6180,8 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_request_msg(LIBLTE_BYTE_MSG_S Document Reference: 24.301 v10.2.0 Section 8.2.8 *********************************************************************/ LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_response_msg(LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT *auth_resp, + uint8 sec_hdr_type, + uint32 count, LIBLTE_BYTE_MSG_STRUCT *msg) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; @@ -6188,6 +6190,21 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_response_msg(LIBLTE_MME_AUTHENT if(auth_resp != 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_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + // Protocol Discriminator and Security Header Type *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); msg_ptr++; diff --git a/lib/src/common/s1ap_pcap.cc b/lib/src/common/s1ap_pcap.cc new file mode 100644 index 000000000..5b32be7f1 --- /dev/null +++ b/lib/src/common/s1ap_pcap.cc @@ -0,0 +1,34 @@ +#include +#include "srslte/srslte.h" +#include "srslte/common/pcap.h" +#include "srslte/common/s1ap_pcap.h" + + +namespace srslte { + +void s1ap_pcap::enable() +{ + enable_write = true; +} +void s1ap_pcap::open(const char* filename) +{ + pcap_file = LTE_PCAP_Open(S1AP_LTE_DLT, filename); + enable_write = true; +} +void s1ap_pcap::close() +{ + fprintf(stdout, "Saving S1AP PCAP file\n"); + LTE_PCAP_Close(pcap_file); +} + +void s1ap_pcap::write_s1ap(uint8_t *pdu, uint32_t pdu_len_bytes) +{ + if (enable_write) { + S1AP_Context_Info_t context; + if (pdu) { + LTE_PCAP_S1AP_WritePDU(pcap_file, &context, pdu, pdu_len_bytes); + } + } +} + +} diff --git a/lib/src/phy/fec/viterbi37_neon.c b/lib/src/phy/fec/viterbi37_neon.c index 82ed190cc..94ddf67cc 100644 --- a/lib/src/phy/fec/viterbi37_neon.c +++ b/lib/src/phy/fec/viterbi37_neon.c @@ -13,7 +13,6 @@ #include "parity.h" //#define DEBUG -//#define HAVE_NEON #ifdef HAVE_NEON #include @@ -22,8 +21,6 @@ typedef union { unsigned char c[64]; uint8x16_t v[4]; } metric_t; - - typedef union { unsigned long w[2]; unsigned char c[8]; @@ -31,18 +28,16 @@ typedef union { uint8x8_t v[1]; } decision_t; - union branchtab27{ - unsigned char c[32]; + unsigned char c[32]; uint8x16_t v[2]; } Branchtab37_neon[3]; - int8_t __attribute__((aligned(16))) xr[8]; - uint8x8_t mask_and; - int8x8_t mask_shift; +int8_t __attribute__((aligned(16))) xr[8]; +uint8x8_t mask_and; +int8x8_t mask_shift; -int firstGo; /* State info for instance of Viterbi decoder */ struct v37 { metric_t metrics1; /* path metric buffer 1 */ @@ -77,7 +72,6 @@ void clear_v37_neon(struct v37 *vp) { int init_viterbi37_neon(void *p, int starting_state) { struct v37 *vp = p; uint32_t i; - firstGo = 1; for(i=0;i<64;i++) vp->metrics1.c[i] = 63; @@ -88,7 +82,6 @@ int init_viterbi37_neon(void *p, int starting_state) { mask_and = vdup_n_u8(0x80); mask_shift = vld1_s8(xr); - vp->old_metrics = &vp->metrics1; vp->new_metrics = &vp->metrics2; vp->dp = vp->decisions; @@ -176,32 +169,31 @@ void print_uint8x16_t(char *s, uint8x16_t val) { printf("\n"); } -static inline int movemask_neon(uint8x16_t movemask_low_in) -{ - uint8x8_t lo = vget_low_u8(movemask_low_in); - uint8x8_t hi = vget_high_u8(movemask_low_in); - lo = vand_u8(lo, mask_and); - lo = vshl_u8(lo, mask_shift); - hi = vand_u8(hi, mask_and); - hi = vshl_u8(hi, mask_shift); +static inline int movemask_neon(uint8x16_t movemask_low_in) { + uint8x8_t lo = vget_low_u8(movemask_low_in); + uint8x8_t hi = vget_high_u8(movemask_low_in); + lo = vand_u8(lo, mask_and); + lo = vshl_u8(lo, mask_shift); + hi = vand_u8(hi, mask_and); + hi = vshl_u8(hi, mask_shift); - lo = vpadd_u8(lo, lo); - lo = vpadd_u8(lo, lo); - lo = vpadd_u8(lo, lo); + lo = vpadd_u8(lo, lo); + lo = vpadd_u8(lo, lo); + lo = vpadd_u8(lo, lo); - hi = vpadd_u8(hi, hi); - hi = vpadd_u8(hi, hi); - hi = vpadd_u8(hi, hi); + hi = vpadd_u8(hi, hi); + hi = vpadd_u8(hi, hi); + hi = vpadd_u8(hi, hi); - return ((hi[0] << 8) | (lo[0] & 0xFF)); + return ((hi[0] << 8) | (lo[0] & 0xFF)); } void update_viterbi37_blk_neon(void *p,unsigned char *syms,int nbits, uint32_t *best_state) { struct v37 *vp = p; decision_t *d; - uint8_t thirtyone; - thirtyone = 31; + uint8_t thirtyone; + thirtyone = 31; if(p == NULL) return; @@ -217,19 +209,18 @@ void update_viterbi37_blk_neon(void *p,unsigned char *syms,int nbits, uint32_t * while(nbits--) { uint8x16_t sym0v,sym1v,sym2v; - void *tmp; int i; // printf("nbits=%d, syms=%d,%d,%d\n", nbits, syms[0], syms[1], syms[2]);fflush(stdout); /* Splat the 0th symbol across sym0v, the 1st symbol across sym1v, etc */ - sym0v = vld1q_dup_u8(syms); // passing a char as opposed to a pointer to a char + sym0v = vld1q_dup_u8(syms); sym1v = vld1q_dup_u8(syms+1); sym2v = vld1q_dup_u8(syms+2); syms += 3; - for(i=0;i<2;i++){ + for(i=0;i<2;i++) { uint8x16_t decision0, decision1, metric, m_metric, m0, m1, m2, m3, survivor0, survivor1; /* Form branch metrics */ @@ -246,48 +237,35 @@ void update_viterbi37_blk_neon(void *p,unsigned char *syms,int nbits, uint32_t * m2 = vaddq_u8(vp->old_metrics->v[i],m_metric); /* Compare and select, using modulo arithmetic */ - - decision0 = (uint8x16_t)vcgtq_s8(vsubq_s8((int8x16_t)m0,(int8x16_t)m1),vdupq_n_s8(0)); decision1 = (uint8x16_t)vcgtq_s8(vsubq_s8((int8x16_t)m2,(int8x16_t)m3),vdupq_n_s8(0)); survivor0 = vorrq_u8(vandq_u8(decision0,m1),vandq_u8(vmvnq_u8(decision0),m0)); survivor1 = vorrq_u8 (vandq_u8(decision1,m3),vandq_u8(vmvnq_u8(decision1),m2) ); - ////// equal to _mm_unpacklo_epi8 ////////// - uint8x8_t a1 = vget_low_u8(decision0); - uint8x8_t b1 = vget_low_u8(decision1); - uint8x8x2_t result = vzip_u8(a1, b1); - uint8x16_t movemask_low_in = vcombine_u8(result.val[0], result.val[1]); - ///////////////////////////////////////// - - - ////////equal to _mm_movemask_epi8 //////// - d->s[2*i] = movemask_neon(movemask_low_in); - - ///////equal to _mm_unpackhi_epi8//////////// - a1 = vget_high_u8(decision0); - b1 = vget_high_u8(decision1); - result = vzip_u8(a1, b1); - uint8x16_t movemask_hi_in = vcombine_u8(result.val[0], result.val[1]); - - + /* Pack each set of decisions into 16 bits */ + uint8x8_t a1 = vget_low_u8(decision0); + uint8x8_t b1 = vget_low_u8(decision1); + uint8x8x2_t result = vzip_u8(a1, b1); + uint8x16_t movemask_low_in = vcombine_u8(result.val[0], result.val[1]); - ////////equal to _mm_movemask////////////// - d->s[2*i+1] = movemask_neon(movemask_hi_in); - - - a1 = vget_low_u8(survivor0); - b1 = vget_low_u8(survivor1); - result = vzip_u8(a1, b1); - vp->new_metrics->v[2*i] = vcombine_u8(result.val[0], result.val[1]); - - - a1 = vget_high_u8(survivor0); - b1 = vget_high_u8(survivor1); - result = vzip_u8(a1, b1); - vp->new_metrics->v[2*i+1] = vcombine_u8(result.val[0], result.val[1]); - - + d->s[2*i] = movemask_neon(movemask_low_in); + + a1 = vget_high_u8(decision0); + b1 = vget_high_u8(decision1); + result = vzip_u8(a1, b1); + uint8x16_t movemask_hi_in = vcombine_u8(result.val[0], result.val[1]); + + d->s[2*i+1] = movemask_neon(movemask_hi_in); + + a1 = vget_low_u8(survivor0); + b1 = vget_low_u8(survivor1); + result = vzip_u8(a1, b1); + vp->new_metrics->v[2*i] = vcombine_u8(result.val[0], result.val[1]); + + a1 = vget_high_u8(survivor0); + b1 = vget_high_u8(survivor1); + result = vzip_u8(a1, b1); + vp->new_metrics->v[2*i+1] = vcombine_u8(result.val[0], result.val[1]); } @@ -315,18 +293,16 @@ void update_viterbi37_blk_neon(void *p,unsigned char *syms,int nbits, uint32_t * /* We cannot use a saturated subtract, because we often have to adjust by more than SHRT_MAX * This is okay since it can't overflow anyway */ - for(i=0;i<4;i++) - { + for(i=0;i<4;i++) { vp->new_metrics->v[i] = vsubq_u8(vp->new_metrics->v[i],adjustv); } - + } d++; /* Swap pointers to old and new metrics */ tmp = vp->old_metrics; vp->old_metrics = vp->new_metrics; vp->new_metrics = tmp; - //firstGo = 0; } if (best_state) { diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index 7fa514e08..c24f0076b 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -130,11 +130,7 @@ void rlc::reestablish() { // defaul lcid=0 is created void rlc::reset() { - for(uint32_t i=0; ideallocate(buf); } + tx_sdu_queue.reset(); +} + +void rlc_am::reestablish() { + stop(); + tx_enabled = true; } void rlc_am::stop() diff --git a/lib/src/upper/rlc_entity.cc b/lib/src/upper/rlc_entity.cc index 4d0573043..783a14982 100644 --- a/lib/src/upper/rlc_entity.cc +++ b/lib/src/upper/rlc_entity.cc @@ -87,7 +87,7 @@ void rlc_entity::configure(srslte_rlc_config_t cnfg) // Reestablishment stops the entity but does not destroy it. Mode will not change void rlc_entity::reestablish() { - rlc->stop(); + rlc->reestablish(); } // A call to stop() stops the entity and clears deletes the instance. Next time this entity can be used for other mode. diff --git a/lib/src/upper/rlc_tm.cc b/lib/src/upper/rlc_tm.cc index c24c1ce29..988acf2af 100644 --- a/lib/src/upper/rlc_tm.cc +++ b/lib/src/upper/rlc_tm.cc @@ -68,6 +68,12 @@ void rlc_tm::empty_queue() while(ul_queue.try_read(&buf)) { pool->deallocate(buf); } + ul_queue.reset(); +} + +void rlc_tm::reestablish() { + stop(); + tx_enabled = true; } void rlc_tm::stop() diff --git a/lib/src/upper/rlc_um.cc b/lib/src/upper/rlc_um.cc index 3ba471724..f0466c9e1 100644 --- a/lib/src/upper/rlc_um.cc +++ b/lib/src/upper/rlc_um.cc @@ -122,6 +122,7 @@ void rlc_um::empty_queue() { while(tx_sdu_queue.try_read(&buf)) { pool->deallocate(buf); } + tx_sdu_queue.reset(); } bool rlc_um::is_mrb() @@ -129,6 +130,11 @@ bool rlc_um::is_mrb() return cfg.is_mrb; } +void rlc_um::reestablish() { + stop(); + tx_enabled = true; +} + void rlc_um::stop() { // Empty tx_sdu_queue before locking the mutex @@ -204,7 +210,7 @@ void rlc_um::write_sdu_nb(byte_buffer_t *sdu) } if (sdu) { if (tx_sdu_queue.try_write(sdu)) { - log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU (%d B,tx_sdu_queue_len=%d)", rrc->get_rb_name(lcid).c_str(), sdu->N_bytes); + log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU (%d B,tx_sdu_queue_len=%d)", rrc->get_rb_name(lcid).c_str(), sdu->N_bytes, tx_sdu_queue.size()); } else { log->debug_hex(sdu->msg, sdu->N_bytes, "[Dropped SDU] %s Tx SDU (%d B,tx_sdu_queue_len=%d)", rrc->get_rb_name(lcid).c_str(), sdu->N_bytes, tx_sdu_queue.size()); pool->deallocate(sdu); diff --git a/srsenb/enb.conf.example b/srsenb/enb.conf.example index 4fa2a5731..1c7c93214 100644 --- a/srsenb/enb.conf.example +++ b/srsenb/enb.conf.example @@ -25,12 +25,12 @@ tac = 0x0007 mcc = 001 mnc = 01 mme_addr = 127.0.1.100 -gtp_bind_addr = 127.0.0.1 +gtp_bind_addr = 127.0.1.1 +s1c_bind_addr = 127.0.1.1 n_prb = 50 #tm = 4 #nof_ports = 2 - ##################################################################### # eNB configuration files # diff --git a/srsenb/hdr/mac/scheduler.h b/srsenb/hdr/mac/scheduler.h index 0c69bcbef..519343097 100644 --- a/srsenb/hdr/mac/scheduler.h +++ b/srsenb/hdr/mac/scheduler.h @@ -151,8 +151,10 @@ private: metric_ul *ul_metric; srslte::log *log_h; rrc_interface_mac *rrc; - - cell_cfg_t cfg; + + pthread_rwlock_t rwlock; + + cell_cfg_t cfg; sched_args_t sched_cfg; const static int MAX_PRB = 100; diff --git a/srsenb/hdr/upper/s1ap.h b/srsenb/hdr/upper/s1ap.h index 284b67d03..b686b6583 100644 --- a/srsenb/hdr/upper/s1ap.h +++ b/srsenb/hdr/upper/s1ap.h @@ -49,6 +49,7 @@ typedef struct { uint16_t mnc; // BCD-coded with 0xF filler std::string mme_addr; std::string gtp_bind_addr; + std::string s1c_bind_addr; std::string enb_name; }s1ap_args_t; diff --git a/srsenb/src/enb.cc b/srsenb/src/enb.cc index f1e237568..c5660e0f0 100644 --- a/srsenb/src/enb.cc +++ b/srsenb/src/enb.cc @@ -205,6 +205,20 @@ bool enb::init(all_args_t *args_) fprintf(stderr, "Error parsing DRB configuration\n"); return false; } + + uint32_t prach_freq_offset = rrc_cfg.sibs[1].sib.sib2.rr_config_common_sib.prach_cnfg.prach_cnfg_info.prach_freq_offset; + + if (prach_freq_offset + 6 > cell_cfg.nof_prb) { + fprintf(stderr, "Invalid PRACH configuration: frequency offset=%d outside bandwidth limits\n", prach_freq_offset); + return false; + } + + if (prach_freq_offset < rrc_cfg.cqi_cfg.nof_prb || prach_freq_offset < rrc_cfg.sr_cfg.nof_prb ) { + fprintf(stderr, "Invalid PRACH configuration: frequency offset=%d lower than CQI offset: %d or SR offset: %d\n", + prach_freq_offset, rrc_cfg.cqi_cfg.nof_prb, rrc_cfg.sr_cfg.nof_prb); + return false; + } + rrc_cfg.inactivity_timeout_ms = args->expert.rrc_inactivity_timer; rrc_cfg.enable_mbsfn = args->expert.enable_mbsfn; diff --git a/srsenb/src/mac/scheduler.cc b/srsenb/src/mac/scheduler.cc index 4bebfb3d9..8737d9168 100644 --- a/srsenb/src/mac/scheduler.cc +++ b/srsenb/src/mac/scheduler.cc @@ -62,11 +62,16 @@ sched::sched() : bc_aggr_level(0), rar_aggr_level(0), avail_rbg(0), P(0), start_ bzero(rar_locations[i], sizeof(sched_ue::sched_dci_cce_t) * 10); } reset(); + + pthread_rwlock_init(&rwlock, NULL); } sched::~sched() { srslte_regs_free(®s); + pthread_rwlock_wrlock(&rwlock); + pthread_rwlock_unlock(&rwlock); + pthread_rwlock_destroy(&rwlock); } void sched::init(rrc_interface_mac *rrc_, srslte::log* log) @@ -86,9 +91,11 @@ int sched::reset() bzero(pending_msg3, sizeof(pending_msg3_t)*10); bzero(pending_rar, sizeof(sched_rar_t)*SCHED_MAX_PENDING_RAR); bzero(pending_sibs, sizeof(sched_sib_t)*MAX_SIBS); + configured = false; + pthread_rwlock_wrlock(&rwlock); ue_db.clear(); - configured = false; - return 0; + pthread_rwlock_unlock(&rwlock); + return 0; } void sched::set_sched_cfg(sched_interface::sched_args_t* sched_cfg_) @@ -152,9 +159,11 @@ int sched::cell_cfg(sched_interface::cell_cfg_t* cell_cfg) int sched::ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t *ue_cfg) { // Add or config user - ue_db[rnti].set_cfg(rnti, ue_cfg, &cfg, ®s, log_h); + pthread_rwlock_rdlock(&rwlock); + ue_db[rnti].set_cfg(rnti, ue_cfg, &cfg, ®s, log_h); ue_db[rnti].set_max_mcs(sched_cfg.pusch_max_mcs, sched_cfg.pdsch_max_mcs); ue_db[rnti].set_fixed_mcs(sched_cfg.pusch_mcs, sched_cfg.pdsch_mcs); + pthread_rwlock_unlock(&rwlock); return 0; } @@ -162,167 +171,198 @@ int sched::ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t *ue_cfg) int sched::ue_rem(uint16_t rnti) { int ret = 0; + pthread_rwlock_wrlock(&rwlock); if (ue_db.count(rnti)) { ue_db.erase(rnti); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } + pthread_rwlock_unlock(&rwlock); return ret; } bool sched::ue_exists(uint16_t rnti) { - return (ue_db.count(rnti) == 1); + pthread_rwlock_rdlock(&rwlock); + bool ret = (ue_db.count(rnti) == 1); + pthread_rwlock_unlock(&rwlock); + return ret; } void sched::phy_config_enabled(uint16_t rnti, bool enabled) { + pthread_rwlock_rdlock(&rwlock); if (ue_db.count(rnti)) { ue_db[rnti].phy_config_enabled(current_tti, enabled); } else { Error("User rnti=0x%x not found\n", rnti); } + pthread_rwlock_unlock(&rwlock); } int sched::bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t *cfg) { int ret = 0; - if (ue_db.count(rnti)) { + pthread_rwlock_rdlock(&rwlock); + if (ue_db.count(rnti)) { ue_db[rnti].set_bearer_cfg(lc_id, cfg); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } + pthread_rwlock_unlock(&rwlock); return ret; } int sched::bearer_ue_rem(uint16_t rnti, uint32_t lc_id) { int ret = 0; - if (ue_db.count(rnti)) { + pthread_rwlock_rdlock(&rwlock); + if (ue_db.count(rnti)) { ue_db[rnti].rem_bearer(lc_id); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } + pthread_rwlock_unlock(&rwlock); return ret; } uint32_t sched::get_dl_buffer(uint16_t rnti) { uint32_t ret = 0; - if (ue_db.count(rnti)) { + pthread_rwlock_rdlock(&rwlock); + if (ue_db.count(rnti)) { ret = ue_db[rnti].get_pending_dl_new_data(current_tti); } else { Error("User rnti=0x%x not found\n", rnti); } + pthread_rwlock_unlock(&rwlock); return ret; } uint32_t sched::get_ul_buffer(uint16_t rnti) { uint32_t ret = 0; - if (ue_db.count(rnti)) { + pthread_rwlock_rdlock(&rwlock); + if (ue_db.count(rnti)) { ret = ue_db[rnti].get_pending_ul_new_data(current_tti); } else { Error("User rnti=0x%x not found\n", rnti); } + pthread_rwlock_unlock(&rwlock); return ret; } int sched::dl_rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue) { int ret = 0; + pthread_rwlock_rdlock(&rwlock); if (ue_db.count(rnti)) { ue_db[rnti].dl_buffer_state(lc_id, tx_queue, retx_queue); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } + pthread_rwlock_unlock(&rwlock); return ret; } int sched::dl_mac_buffer_state(uint16_t rnti, uint32_t ce_code) { int ret = 0; - if (ue_db.count(rnti)) { + pthread_rwlock_rdlock(&rwlock); + if (ue_db.count(rnti)) { ue_db[rnti].mac_buffer_state(ce_code); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } + pthread_rwlock_unlock(&rwlock); return ret; } int sched::dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dl_ant_info) { int ret = 0; + pthread_rwlock_rdlock(&rwlock); if (ue_db.count(rnti)) { ue_db[rnti].set_dl_ant_info(dl_ant_info); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } + pthread_rwlock_unlock(&rwlock); return ret; } int sched::dl_ack_info(uint32_t tti, uint16_t rnti, uint32_t tb_idx, bool ack) { int ret = 0; - if (ue_db.count(rnti)) { + pthread_rwlock_rdlock(&rwlock); + if (ue_db.count(rnti)) { ret = ue_db[rnti].set_ack_info(tti, tb_idx, ack); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } + pthread_rwlock_unlock(&rwlock); return ret; } int sched::ul_crc_info(uint32_t tti, uint16_t rnti, bool crc) { int ret = 0; - if (ue_db.count(rnti)) { + pthread_rwlock_rdlock(&rwlock); + if (ue_db.count(rnti)) { ue_db[rnti].set_ul_crc(tti, crc); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } + pthread_rwlock_unlock(&rwlock); return ret; } int sched::dl_ri_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) { int ret = 0; - if (ue_db.count(rnti)) { + pthread_rwlock_rdlock(&rwlock); + if (ue_db.count(rnti)) { ue_db[rnti].set_dl_ri(tti, cqi_value); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } + pthread_rwlock_unlock(&rwlock); return ret; } int sched::dl_pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value) { int ret = 0; + pthread_rwlock_rdlock(&rwlock); if (ue_db.count(rnti)) { ue_db[rnti].set_dl_pmi(tti, pmi_value); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } + pthread_rwlock_unlock(&rwlock); return ret; } int sched::dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) { int ret = 0; + pthread_rwlock_rdlock(&rwlock); if (ue_db.count(rnti)) { ue_db[rnti].set_dl_cqi(tti, cqi_value); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } + pthread_rwlock_unlock(&rwlock); return ret; } @@ -345,79 +385,93 @@ int sched::dl_rach_info(uint32_t tti, uint32_t ra_id, uint16_t rnti, uint32_t es int sched::ul_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi, uint32_t ul_ch_code) { int ret = 0; - if (ue_db.count(rnti)) { + pthread_rwlock_rdlock(&rwlock); + if (ue_db.count(rnti)) { ue_db[rnti].set_ul_cqi(tti, cqi, ul_ch_code); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } + pthread_rwlock_unlock(&rwlock); return ret; } int sched::ul_bsr(uint16_t rnti, uint32_t lcid, uint32_t bsr, bool set_value) { int ret = 0; - if (ue_db.count(rnti)) { + pthread_rwlock_rdlock(&rwlock); + if (ue_db.count(rnti)) { ue_db[rnti].ul_buffer_state(lcid, bsr, set_value); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } + pthread_rwlock_unlock(&rwlock); return ret; } int sched::ul_recv_len(uint16_t rnti, uint32_t lcid, uint32_t len) { int ret = 0; - if (ue_db.count(rnti)) { + pthread_rwlock_rdlock(&rwlock); + if (ue_db.count(rnti)) { ue_db[rnti].ul_recv_len(lcid, len); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } + pthread_rwlock_unlock(&rwlock); return ret; } int sched::ul_phr(uint16_t rnti, int phr) { int ret = 0; - if (ue_db.count(rnti)) { + pthread_rwlock_rdlock(&rwlock); + if (ue_db.count(rnti)) { ue_db[rnti].ul_phr(phr); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } + pthread_rwlock_unlock(&rwlock); return ret; } int sched::ul_sr_info(uint32_t tti, uint16_t rnti) { int ret = 0; - if (ue_db.count(rnti)) { + pthread_rwlock_rdlock(&rwlock); + if (ue_db.count(rnti)) { ue_db[rnti].set_sr();; } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; } + pthread_rwlock_unlock(&rwlock); return ret; } void sched::tpc_inc(uint16_t rnti) { - if (ue_db.count(rnti)) { + pthread_rwlock_rdlock(&rwlock); + if (ue_db.count(rnti)) { ue_db[rnti].tpc_inc(); } else { Error("User rnti=0x%x not found\n", rnti); } + pthread_rwlock_unlock(&rwlock); } void sched::tpc_dec(uint16_t rnti) { - if (ue_db.count(rnti)) { + pthread_rwlock_rdlock(&rwlock); + if (ue_db.count(rnti)) { ue_db[rnti].tpc_dec(); } else { Error("User rnti=0x%x not found\n", rnti); } + pthread_rwlock_unlock(&rwlock); } /******************************************************* @@ -714,6 +768,8 @@ int sched::dl_sched(uint32_t tti, sched_interface::dl_sched_res_t* sched_result) rar_aggr_level = 2; bzero(sched_result, sizeof(sched_interface::dl_sched_res_t)); + pthread_rwlock_rdlock(&rwlock); + /* Schedule Broadcast data */ sched_result->nof_bc_elems += dl_sched_bc(sched_result->bc); @@ -722,7 +778,9 @@ int sched::dl_sched(uint32_t tti, sched_interface::dl_sched_res_t* sched_result) /* Schedule pending RLC data */ sched_result->nof_data_elems += dl_sched_data(sched_result->data); - + + pthread_rwlock_unlock(&rwlock); + /* Set CFI */ sched_result->cfi = current_cfi; @@ -733,10 +791,16 @@ int sched::dl_sched(uint32_t tti, sched_interface::dl_sched_res_t* sched_result) int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched_result) { typedef std::map::iterator it_t; + if (!configured) { return 0; } + if (cfg.prach_freq_offset + 6 > cfg.cell.nof_prb) { + fprintf(stderr, "Invalid PRACH configuration: frequency offset=%d outside bandwidth limits\n", cfg.prach_freq_offset); + return -1; + } + /* If dl_sched() not yet called this tti (this tti is +4ms advanced), reset CCE state */ if (TTI_TX(current_tti) != tti) { bzero(used_cce, MAX_CCE*sizeof(bool)); @@ -757,6 +821,8 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched bzero(sched_result, sizeof(sched_interface::ul_sched_res_t)); ul_metric->reset_allocation(cfg.cell.nof_prb); + pthread_rwlock_rdlock(&rwlock); + // Get HARQ process for this TTI for(it_t iter=ue_db.begin(); iter!=ue_db.end(); ++iter) { sched_ue *user = (sched_ue*) &iter->second; @@ -819,10 +885,6 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched ul_harq_proc::ul_alloc_t prach = {cfg.prach_freq_offset, 6}; if(!ul_metric->update_allocation(prach)) { log_h->warning("SCHED: Failed to allocate PRACH RBs within (%d,%d)\n", prach.RB_start, prach.RB_start + prach.L); - if (prach.RB_start + prach.L > cfg.cell.nof_prb) { - fprintf(stderr, "Invalid PRACH configuration: frequency offset=%d outside bandwidth limits\n", cfg.prach_freq_offset); - return -1; - } } else { log_h->debug("SCHED: Allocated PRACH RBs within (%d,%d)\n", prach.RB_start, prach.RB_start + prach.L); @@ -931,6 +993,8 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched user->get_ul_harq(current_tti)->reset_pending_data(); } + pthread_rwlock_unlock(&rwlock); + sched_result->nof_dci_elems = nof_dci_elems; sched_result->nof_phich_elems = nof_phich_elems; diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 5c86570d8..6926eb23f 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -78,6 +78,7 @@ void parse_args(all_args_t *args, int argc, char* argv[]) { ("enb.mnc", bpo::value(&mnc)->default_value("01"), "Mobile Network Code") ("enb.mme_addr", bpo::value(&args->enb.s1ap.mme_addr)->default_value("127.0.0.1"),"IP address of MME for S1 connnection") ("enb.gtp_bind_addr", bpo::value(&args->enb.s1ap.gtp_bind_addr)->default_value("192.168.3.1"), "Local IP address to bind for GTP connection") + ("enb.s1c_bind_addr", bpo::value(&args->enb.s1ap.s1c_bind_addr)->default_value("192.168.3.1"), "Local IP address to bind for S1AP connection") ("enb.phy_cell_id", bpo::value(&args->enb.pci)->default_value(0), "Physical Cell Identity (PCI)") ("enb.n_prb", bpo::value(&args->enb.n_prb)->default_value(25), "Number of PRB") ("enb.nof_ports", bpo::value(&args->enb.nof_ports)->default_value(1), "Number of ports") diff --git a/srsenb/src/upper/gtpu.cc b/srsenb/src/upper/gtpu.cc index 0f8bc3325..1d90fd388 100644 --- a/srsenb/src/upper/gtpu.cc +++ b/srsenb/src/upper/gtpu.cc @@ -35,6 +35,12 @@ namespace srsenb { gtpu::gtpu():mchthread() { + pdcp = NULL; + gtpu_log = NULL; + pool = NULL; + + pthread_mutex_init(&mutex, NULL); + } bool gtpu::init(std::string gtp_bind_addr_, std::string mme_addr_, srsenb::pdcp_interface_gtpu* pdcp_, srslte::log* gtpu_log_, bool enable_mbsfn) @@ -44,8 +50,6 @@ bool gtpu::init(std::string gtp_bind_addr_, std::string mme_addr_, srsenb::pdcp_ gtp_bind_addr = gtp_bind_addr_; mme_addr = mme_addr_; - pthread_mutex_init(&mutex, NULL); - pool = byte_buffer_pool::get_instance(); // Set up sink socket @@ -155,12 +159,17 @@ void gtpu::write_pdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* pdu) pool->deallocate(pdu); } -// gtpu_interface_rrc +/* Warning: This function is called before calling gtpu::init() during MCCH initialization. + * If access to any element created in init (such as gtpu_log) is required, it must be considered + * the case of it being NULL. + */ void gtpu::add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, uint32_t *teid_in) { // Allocate a TEID for the incoming tunnel rntilcid_to_teidin(rnti, lcid, teid_in); - //gtpu_log->info("Adding bearer for rnti: 0x%x, lcid: %d, addr: 0x%x, teid_out: 0x%x, teid_in: 0x%x\n", rnti, lcid, addr, teid_out, *teid_in); + if (gtpu_log) { + gtpu_log->info("Adding bearer for rnti: 0x%x, lcid: %d, addr: 0x%x, teid_out: 0x%x, teid_in: 0x%x\n", rnti, lcid, addr, teid_out, *teid_in); + } // Initialize maps if it's a new RNTI if(rnti_bearers.count(rnti) == 0) { @@ -178,6 +187,7 @@ void gtpu::add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid void gtpu::rem_bearer(uint16_t rnti, uint32_t lcid) { + pthread_mutex_lock(&mutex); gtpu_log->info("Removing bearer for rnti: 0x%x, lcid: %d\n", rnti, lcid); rnti_bearers[rnti].teids_in[lcid] = 0; @@ -193,6 +203,7 @@ void gtpu::rem_bearer(uint16_t rnti, uint32_t lcid) if(rem) { rnti_bearers.erase(rnti); } + pthread_mutex_unlock(&mutex); } void gtpu::rem_user(uint16_t rnti) diff --git a/srsenb/src/upper/s1ap.cc b/srsenb/src/upper/s1ap.cc index 8cc4bebda..1e2b25987 100644 --- a/srsenb/src/upper/s1ap.cc +++ b/srsenb/src/upper/s1ap.cc @@ -274,8 +274,8 @@ bool s1ap::connect_mme() memset(&local_addr, 0, sizeof(struct sockaddr_in)); local_addr.sin_family = ADDR_FAMILY; local_addr.sin_port = 0; // Any local port will do - if(inet_pton(AF_INET, args.gtp_bind_addr.c_str(), &(local_addr.sin_addr)) != 1) { - s1ap_log->error("Error converting IP address (%s) to sockaddr_in structure\n", args.gtp_bind_addr.c_str()); + if(inet_pton(AF_INET, args.s1c_bind_addr.c_str(), &(local_addr.sin_addr)) != 1) { + s1ap_log->error("Error converting IP address (%s) to sockaddr_in structure\n", args.s1c_bind_addr.c_str()); return false; } bind(socket_fd, (struct sockaddr *)&local_addr, sizeof(local_addr)); diff --git a/srsepc/epc.conf.example b/srsepc/epc.conf.example index 02ef797ef..6d857f78a 100644 --- a/srsepc/epc.conf.example +++ b/srsepc/epc.conf.example @@ -45,8 +45,24 @@ db_file = user_db.csv ##################################################################### [spgw] -gtpu_bind_addr=127.0.1.100 -sgi_if_addr=172.16.0.1 +gtpu_bind_addr = 127.0.1.100 +sgi_if_addr = 172.16.0.1 + +#################################################################### +# PCAP configuration +# +# Packets are captured to file in the compact format decoded by +# the Wireshark s1ap dissector and with DLT 150. +# To use the dissector, edit the preferences for DLT_USER to +# add an entry with DLT=150, Payload Protocol=s1ap. +# +# enable: Enable or disable the PCAP. +# filename: File name where to save the PCAP. +# +#################################################################### +[pcap] +enable = false +filename = /tmp/epc.pcap #################################################################### # Log configuration diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index ebedc9fec..4cb8385e0 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -31,6 +31,7 @@ #include "srslte/asn1/liblte_mme.h" #include "srslte/common/common.h" #include "srslte/common/log.h" +#include "srslte/common/s1ap_pcap.h" #include #include @@ -66,6 +67,7 @@ public: void delete_enb_ctx(int32_t assoc_id); + bool s1ap_tx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb_sri); 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_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *msg); @@ -125,6 +127,10 @@ private: //FIXME the GTP-C should be moved to the MME class, when the packaging of GTP-C messages is done. mme_gtpc *m_mme_gtpc; + + //PCAP + bool m_pcap_enable; + srslte::s1ap_pcap m_pcap; }; inline uint32_t diff --git a/srsepc/hdr/mme/s1ap_common.h b/srsepc/hdr/mme/s1ap_common.h index 262d034b1..e5c198748 100644 --- a/srsepc/hdr/mme/s1ap_common.h +++ b/srsepc/hdr/mme/s1ap_common.h @@ -93,6 +93,8 @@ typedef struct{ std::string mme_name; std::string dns_addr; std::string mme_apn; + bool pcap_enable; + std::string pcap_filename; } s1ap_args_t; typedef struct{ diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index 24e507f6f..2255d9e4c 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -100,35 +100,38 @@ parse_args(all_args_t *args, int argc, char* argv[]) { bpo::options_description common("Configuration options"); common.add_options() - ("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") - ("mme.dns_addr", bpo::value(&dns_addr)->default_value("8.8.8.8"),"IP address of the DNS server for the UEs") - ("mme.apn", bpo::value(&mme_apn)->default_value(""), "Set Access Point Name (APN) for data services") - ("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") - - ("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") + ("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") + ("mme.dns_addr", bpo::value(&dns_addr)->default_value("8.8.8.8"), "IP address of the DNS server for the UEs") + ("mme.apn", bpo::value(&mme_apn)->default_value(""), "Set Access Point Name (APN) for data services") + ("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") + + ("pcap.enable", bpo::value(&args->mme_args.s1ap_args.pcap_enable)->default_value(false), "Enable S1AP PCAP") + ("pcap.filename", bpo::value(&args->mme_args.s1ap_args.pcap_filename)->default_value("/tmp/epc.pcap"), "PCAP filename") + + ("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.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.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") + ("log.filename", bpo::value(&args->log_args.filename)->default_value("/tmp/epc.log"),"Log filename") ; // Positional options - config file location @@ -141,7 +144,7 @@ parse_args(all_args_t *args, int argc, char* argv[]) { // these options are allowed on the command line bpo::options_description cmdline_options; - cmdline_options.add(common).add(position).add(general); + cmdline_options.add(common).add(position).add(general); // parse the command line and store result in vm bpo::variables_map vm; @@ -288,12 +291,11 @@ main (int argc,char * argv[] ) all_args_t args; parse_args(&args, argc, argv); - + srslte::logger_stdout logger_stdout; srslte::logger_file logger_file; srslte::logger *logger; - /*Init logger*/ if (!args.log_args.filename.compare("stdout")) { logger = &logger_stdout; @@ -340,16 +342,16 @@ main (int argc,char * argv[] ) if (spgw->init(&args.spgw_args,&spgw_log)) { cout << "Error initializing SP-GW" << endl; exit(1); - } + } - mme->start(); + mme->start(); spgw->start(); while(running) { sleep(1); } mme->stop(); - mme->cleanup(); + mme->cleanup(); spgw->stop(); spgw->cleanup(); hss->stop(); diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 180859f08..3c6e6dbe3 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -99,6 +99,11 @@ s1ap::init(s1ap_args_t s1ap_args, srslte::log_filter *s1ap_log, hss_interface_s1 //Initialize S1-MME m_s1mme = enb_listen(); + //Init PCAP + m_pcap_enable = s1ap_args.pcap_enable; + if(m_pcap_enable){ + m_pcap.open(s1ap_args.pcap_filename.c_str()); + } m_s1ap_log->info("S1AP Initialized\n"); return 0; } @@ -130,6 +135,12 @@ s1ap::stop() s1ap_mngmt_proc::cleanup(); s1ap_nas_transport::cleanup(); s1ap_ctx_mngmt_proc::cleanup(); + + //PCAP + if(m_pcap_enable){ + m_pcap.close(); + } + return; } @@ -174,7 +185,7 @@ s1ap::enb_listen() //S1-MME bind bzero(&s1mme_addr, sizeof(s1mme_addr)); - s1mme_addr.sin_family = AF_INET; + s1mme_addr.sin_family = AF_INET; 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)); @@ -197,6 +208,20 @@ s1ap::enb_listen() return sock_fd; } +bool +s1ap::s1ap_tx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb_sri) +{ + ssize_t n_sent = sctp_send(m_s1mme, pdu->msg, pdu->N_bytes, enb_sri, 0); + if(n_sent == -1){ + m_s1ap_log->console("Failed to send S1AP PDU.\n"); + m_s1ap_log->error("Failed to send S1AP PDU. \n"); + return false; + } + if(m_pcap_enable){ + m_pcap.write_s1ap(pdu->msg,pdu->N_bytes); + } + return true; +} bool s1ap::handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb_sri) @@ -208,6 +233,10 @@ s1ap::handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb return false; } + if(m_pcap_enable){ + m_pcap.write_s1ap(pdu->msg,pdu->N_bytes); + } + switch(rx_pdu.choice_type) { case LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE: m_s1ap_log->info("Received initiating PDU\n"); @@ -235,6 +264,7 @@ s1ap::handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, stru { bool reply_flag = false; srslte::byte_buffer_t * reply_buffer = m_pool->allocate(); + bool ret = false; switch(msg->choice_type) { case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_S1SETUPREQUEST: @@ -257,23 +287,17 @@ s1ap::handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, stru m_s1ap_log->error("Unhandled S1AP intiating message: %s\n", liblte_s1ap_initiatingmessage_choice_text[msg->choice_type]); m_s1ap_log->console("Unhandled S1APintiating 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 S1AP Initiating Reply.\n"); - m_s1ap_log->error("Failed to send S1AP Initiating Reply. \n"); - m_pool->deallocate(reply_buffer); - return false; - } + if(reply_flag == true){ + ret = s1ap_tx_pdu(reply_buffer, enb_sri); } + m_pool->deallocate(reply_buffer); - return true; + return ret; } -bool +bool s1ap::handle_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *msg) { switch(msg->choice_type) { @@ -496,7 +520,7 @@ s1ap::release_ue_ecm_ctx(uint32_t mme_ue_s1ap_id) m_s1ap_log->error("Could not find eNB for UE release request.\n"); return false; } - uint16_t enb_id = it->second; + uint16_t enb_id = it->second; std::map >::iterator ue_set = m_enb_assoc_to_ue_ids.find(ecm_ctx->enb_sri.sinfo_assoc_id); if(ue_set == m_enb_assoc_to_ue_ids.end()) { diff --git a/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc index b9d599d3e..37abf06f4 100644 --- a/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc +++ b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc @@ -96,7 +96,7 @@ s1ap_ctx_mngmt_proc::send_initial_context_setup_request(ue_emm_ctx_t *emm_ctx, 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_ctx_req = &in_ctxt_req->E_RABToBeSetupListCtxtSUReq.buffer[0]; //FIXME support more than one erab srslte::byte_buffer_t *reply_buffer = m_pool->allocate(); @@ -136,34 +136,28 @@ s1ap_ctx_mngmt_proc::send_initial_context_setup_request(ue_emm_ctx_t *emm_ctx, memcpy(erab_ctx_req->gTP_TEID.buffer, &sgw_s1u_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(emm_ctx->security_ctxt.ue_network_cap.eea[i+1] == true) - { + 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(emm_ctx->security_ctxt.ue_network_cap.eea[i+1] == true){ in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer[i] = 1; //EEA supported - } - else - { + } else { in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer[i] = 0; //EEA not supported } - if(emm_ctx->security_ctxt.ue_network_cap.eia[i+1] == true) - { + if(emm_ctx->security_ctxt.ue_network_cap.eia[i+1] == true){ in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[i] = 1; //EEA supported - } - else - { + } else { in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[i] = 0; //EEA not supported } } + //Get K eNB liblte_unpack(emm_ctx->security_ctxt.k_enb, 32, in_ctxt_req->SecurityKey.buffer); m_s1ap_log->info_hex(emm_ctx->security_ctxt.k_enb, 32, "Initial Context Setup Request -- Key eNB (k_enb)\n"); srslte::byte_buffer_t *nas_buffer = m_pool->allocate(); - if(emm_ctx->state == EMM_STATE_DEREGISTERED) - { + if (emm_ctx->state == EMM_STATE_DEREGISTERED) { //Attach procedure initiated from an attach request m_s1ap_log->console("Adding attach accept to Initial Context Setup Request\n"); m_s1ap_log->info("Adding attach accept to Initial Context Setup Request\n"); @@ -172,18 +166,14 @@ s1ap_ctx_mngmt_proc::send_initial_context_setup_request(ue_emm_ctx_t *emm_ctx, LIBLTE_ERROR_ENUM err = liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)reply_buffer); - if(err != LIBLTE_SUCCESS) - { + 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(s1mme,reply_buffer->msg, reply_buffer->N_bytes, &ecm_ctx->enb_sri, 0); - if(n_sent == -1) - { - m_s1ap_log->error("Failed to send Initial Context Setup Request\n"); - return false; + if (!m_s1ap->s1ap_tx_pdu(reply_buffer,&ecm_ctx->enb_sri)) { + m_s1ap_log->error("Error sending Initial Context Setup Request.\n"); + return false; } //Change E-RAB state to Context Setup Requested and save S-GW control F-TEID @@ -345,31 +335,18 @@ s1ap_ctx_mngmt_proc::send_ue_context_release_command(ue_ecm_ctx_t *ecm_ctx, srsl return false; } //Send Reply to eNB - int n_sent = sctp_send(s1mme,reply_buffer->msg, reply_buffer->N_bytes, &ecm_ctx->enb_sri, 0); - if(n_sent == -1) + if(!m_s1ap->s1ap_tx_pdu(reply_buffer,&ecm_ctx->enb_sri)) { - m_s1ap_log->error("Failed to send Initial Context Setup Request\n"); + m_s1ap_log->error("Error sending UE Context Release command.\n"); return false; } - return true; } bool s1ap_ctx_mngmt_proc::handle_ue_context_release_complete(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASECOMPLETE_STRUCT *rel_comp) { - /* - 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_CRITICALITYDIAGNOSTICS_STRUCT CriticalityDiagnostics; - bool CriticalityDiagnostics_present; - LIBLTE_S1AP_USERLOCATIONINFORMATION_STRUCT UserLocationInformation; - bool UserLocationInformation_present; - }LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASECOMPLETE_STRUCT; - */ uint32_t mme_ue_s1ap_id = rel_comp->MME_UE_S1AP_ID.MME_UE_S1AP_ID; m_s1ap_log->info("Received UE Context Release Complete. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); @@ -385,23 +362,19 @@ s1ap_ctx_mngmt_proc::handle_ue_context_release_complete(LIBLTE_S1AP_MESSAGE_UECO ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx; //Delete user plane context at the SPGW (but keep GTP-C connection). - if (ecm_ctx->state == ECM_STATE_CONNECTED) - { + if (ecm_ctx->state == ECM_STATE_CONNECTED) { //There are active E-RABs, send release access mearers request m_s1ap_log->console("There are active E-RABs, send release access mearers request"); m_s1ap_log->info("There are active E-RABs, send release access mearers request"); m_mme_gtpc->send_release_access_bearers_request(ecm_ctx->imsi); //The handle_releease_access_bearers_response function will make sure to mark E-RABS DEACTIVATED //It will release the UEs downstream S1-u and keep the upstream S1-U connection active. - } - else - { + } else { //No ECM Context to release m_s1ap_log->info("UE is not ECM connected. No need to release S1-U. MME UE S1AP Id %d\n", mme_ue_s1ap_id); m_s1ap_log->console("UE is not ECM connected. No need to release S1-U. MME UE S1AP Id %d\n", mme_ue_s1ap_id); - //Make sure E-RABS are merked as DEACTIVATED. - for(int i=0;ierabs_ctx[i].state = ERAB_DEACTIVATED; } } diff --git a/srsue/hdr/mac/ul_harq.h b/srsue/hdr/mac/ul_harq.h index 6fb27be8a..d62a94aba 100644 --- a/srsue/hdr/mac/ul_harq.h +++ b/srsue/hdr/mac/ul_harq.h @@ -227,7 +227,7 @@ private: if (grant->has_cqi_request && grant->phy_grant.ul.mcs.tbs == 0) { /* Only CQI reporting (without SCH) */ memcpy(&action->phy_grant.ul, &grant->phy_grant.ul, sizeof(srslte_ra_ul_grant_t)); - memcpy(&cur_grant, grant, sizeof(Tgrant)); + //memcpy(&cur_grant, grant, sizeof(Tgrant)); action->tx_enabled = true; action->rnti = grant->rnti; } else if ((!(grant->rnti_type == SRSLTE_RNTI_TEMP) && grant->ndi[0] != get_ndi() && harq_feedback) || diff --git a/srsue/hdr/upper/nas.h b/srsue/hdr/upper/nas.h index 85c7a2f8e..32f6898f9 100644 --- a/srsue/hdr/upper/nas.h +++ b/srsue/hdr/upper/nas.h @@ -166,7 +166,7 @@ private: // Parsers void parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu); void parse_attach_reject(uint32_t lcid, byte_buffer_t *pdu); - void parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu); + void parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu, const uint8_t sec_hdr_type); void parse_authentication_reject(uint32_t lcid, byte_buffer_t *pdu); void parse_identity_request(uint32_t lcid, byte_buffer_t *pdu); void parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu); @@ -182,7 +182,7 @@ private: void send_identity_response(); void send_service_request(); void send_esm_information_response(const uint8 proc_transaction_id); - void send_authentication_response(const uint8_t* res, const size_t res_len); + void send_authentication_response(const uint8_t* res, const size_t res_len, const uint8_t sec_hdr_type); void send_authentication_failure(const uint8_t cause, const uint8_t* auth_fail_param); void gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg); void send_security_mode_reject(uint8_t cause); diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 8ab51d90c..9f9ef945d 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -26,8 +26,6 @@ #include #include -#include -#include #include "srslte/srslte.h" #include "srslte/common/log.h" #include "srsue/hdr/phy/phch_worker.h" diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index 2e491b733..5601896b5 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -250,7 +250,6 @@ bool nas::rrc_connect() { } } else { nas_log->error("Could not establish RRC connection\n"); - pool->deallocate(dedicatedInfoNAS); } return false; } @@ -331,7 +330,7 @@ void nas::write_pdu(uint32_t lcid, byte_buffer_t *pdu) { parse_attach_reject(lcid, pdu); break; case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_REQUEST: - parse_authentication_request(lcid, pdu); + parse_authentication_request(lcid, pdu, sec_hdr_type); break; case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_REJECT: parse_authentication_reject(lcid, pdu); @@ -722,7 +721,7 @@ void nas::parse_attach_reject(uint32_t lcid, byte_buffer_t *pdu) { // FIXME: Command RRC to release? } -void nas::parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu) { +void nas::parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu, const uint8_t sec_hdr_type) { LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT auth_req; bzero(&auth_req, sizeof(LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT)); @@ -756,8 +755,8 @@ void nas::parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu) { if (auth_result == AUTH_OK) { nas_log->info("Network authentication successful\n"); - send_authentication_response(res, res_len); - nas_log->info("Generated k_asme=%s\n", hex_to_string(ctxt.k_asme, 32).c_str()); + send_authentication_response(res, res_len, sec_hdr_type); + nas_log->info_hex(ctxt.k_asme, 32, "Generated k_asme:\n"); } else if (auth_result == AUTH_SYNCH_FAILURE) { nas_log->error("Network authentication synchronization failure.\n"); send_authentication_failure(LIBLTE_MME_EMM_CAUSE_SYNCH_FAILURE, res); @@ -878,8 +877,8 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu) // Generate NAS keys usim->generate_nas_keys(ctxt.k_asme, k_nas_enc, k_nas_int, ctxt.cipher_algo, ctxt.integ_algo); - nas_log->debug_hex(k_nas_enc, 32, "NAS encryption key - k_nas_enc"); - nas_log->debug_hex(k_nas_int, 32, "NAS integrity key - k_nas_int"); + nas_log->info_hex(k_nas_enc, 32, "NAS encryption key - k_nas_enc"); + nas_log->info_hex(k_nas_int, 32, "NAS integrity key - k_nas_int"); nas_log->debug("Generating integrity check. integ_algo:%d, count_dl:%d, lcid:%d\n", ctxt.integ_algo, ctxt.rx_count, lcid); @@ -1129,9 +1128,9 @@ void nas::send_security_mode_reject(uint8_t cause) { } -void nas::send_authentication_response(const uint8_t* res, const size_t res_len) { - byte_buffer_t *msg = pool_allocate; - if (!msg) { +void nas::send_authentication_response(const uint8_t* res, const size_t res_len, const uint8_t sec_hdr_type) { + byte_buffer_t *pdu = pool_allocate; + if (!pdu) { nas_log->error("Fatal Error: Couldn't allocate PDU in send_authentication_response().\n"); return; } @@ -1143,13 +1142,24 @@ void nas::send_authentication_response(const uint8_t* res, const size_t res_len) auth_res.res[i] = res[i]; } auth_res.res_len = res_len; - liblte_mme_pack_authentication_response_msg(&auth_res, (LIBLTE_BYTE_MSG_STRUCT *)msg); + liblte_mme_pack_authentication_response_msg(&auth_res, sec_hdr_type, ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT *)pdu); if(pcap != NULL) { - pcap->write_nas(msg->msg, msg->N_bytes); + pcap->write_nas(pdu->msg, pdu->N_bytes); + } + + if (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED && pdu->N_bytes > 5) { + cipher_encrypt(pdu); + integrity_generate(&k_nas_int[16], + ctxt.tx_count, + SECURITY_DIRECTION_UPLINK, + &pdu->msg[5], + pdu->N_bytes - 5, + &pdu->msg[1]); } + nas_log->info("Sending Authentication Response\n"); - rrc->write_sdu(cfg.lcid, msg); + rrc->write_sdu(cfg.lcid, pdu); } diff --git a/srsue/src/upper/pcsc_usim.cc b/srsue/src/upper/pcsc_usim.cc index d94bebe1a..0d423c73c 100644 --- a/srsue/src/upper/pcsc_usim.cc +++ b/srsue/src/upper/pcsc_usim.cc @@ -250,7 +250,7 @@ auth_result_t pcsc_usim::generate_authentication_response(uint8_t *rand, mcc, mnc, k_asme); - log->debug_hex(k_asme, KEY_LEN, "K_ASME:\n"); + log->info_hex(k_asme, KEY_LEN, "K_ASME:\n"); ret = AUTH_OK; diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 66a7de33e..440b4a318 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -526,6 +526,12 @@ bool rrc::connection_request(LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM cause, } } + if (!ret) { + rrc_log->warning("Could not estblish connection. Deallocating dedicatedInfoNAS PDU\n"); + pool->deallocate(this->dedicatedInfoNAS); + this->dedicatedInfoNAS = NULL; + } + pthread_mutex_unlock(&mutex); return ret; } @@ -2036,9 +2042,9 @@ void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu) { uint8_t k_asme[32]; nas->get_k_asme(k_asme, 32); usim->generate_as_keys(k_asme, nas->get_ul_count(), k_rrc_enc, k_rrc_int, k_up_enc, k_up_int, cipher_algo, integ_algo); - rrc_log->debug_hex(k_rrc_enc, 32, "RRC encryption key - k_rrc_enc"); - rrc_log->debug_hex(k_rrc_int, 32, "RRC integrity key - k_rrc_int"); - rrc_log->debug_hex(k_up_enc, 32, "UP encryption key - k_up_enc"); + rrc_log->info_hex(k_rrc_enc, 32, "RRC encryption key - k_rrc_enc"); + rrc_log->info_hex(k_rrc_int, 32, "RRC integrity key - k_rrc_int"); + rrc_log->info_hex(k_up_enc, 32, "UP encryption key - k_up_enc"); security_is_activated = true; diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index eeef5531b..3d56d19fb 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -122,7 +122,7 @@ imei = 353490069873319 # apn: Set Access Point Name (APN) # user: Username for CHAP authentication # pass: Password for CHAP authentication -# force_imsi_attach: Whether to always perform an IMSI +# force_imsi_attach: Whether to always perform an IMSI attach ##################################################################### [nas] #apn = internetinternet @@ -168,7 +168,6 @@ enable = false # estimator_fil_stddev: Sets the channel estimator smooth gaussian filter standard deviation. # estimator_fil_order: Sets the channel estimator smooth gaussian filter order (even values perform better). # The taps are [w, 1-2w, w] -# metrics_period_secs: Sets the period at which metrics are requested from the UE. # # pregenerate_signals: Pregenerate uplink signals after attach. Improves CPU performance. # @@ -181,6 +180,8 @@ enable = false # # metrics_csv_enable: Write UE metrics to CSV file. # +# metrics_period_secs: Sets the period at which metrics are requested from the UE. +# # metrics_csv_filename: File path to use for CSV metrics. # # cfo_integer_enabled: Enables integer CFO estimation and correction. This needs improvement @@ -230,6 +231,7 @@ enable = false #sic_pss_enabled = true #pregenerate_signals = false #metrics_csv_enable = false +#metrics_period_secs = 1 #metrics_csv_filename = /tmp/ue_metrics.csv #pdsch_csi_enabled = true