📜 âŹ†ïž âŹ‡ïž

LLTR Part 1: First steps in OMNeT ++ and INET

OMNeT ++ (Binary Multiple N etwork T estbed in C ++ ) Discrete Event Simulator is a modular, component-oriented C ++ library and framework for discrete-event modeling , used primarily to create network simulators . Simply put, this is a “discrete event simulator”, which includes: an IDE for creating models, and the simulator itself (GUI).


The INET Framework is the “library” of network models for OMNeT ++ .


: LLTR  1 – OMNeT++ 5 the Open Simulator :: LLTR Model :: for freedom use


Full version GIF (15.7 MiB)


In the previous parts ...


0. Automatic detection of network topology and unmanaged switches. Mission Impossible? (+ classic Habrahabr UserCSS )


In this part:



Note : additional information for readers of the “Mesh-network” hub.


{image size: 2.2+ (2.1) MiB; text: 484 KiB; Smileys: 22 pcs. }


Note : [about the structure of sections used] the structure of the tutorial / how-to sections usually differs from the structure of the sections in the directory: in the directory - the structure of the sections allows you to reach the required information in a minimum number of steps (balanced tree); in tutorial / how ‑ to, where sections are strongly connected logically, and a separate section, in fact, is one of the steps in the sequence of steps, the structure is a hierarchy of bookmarks (anchors), which allows you to remind (tutorial / ) about the fragment described earlier.


off ‑ topic: about html5 <section> tag and title tags <h #>

As it is good that the <section> tag appeared in HTML5, with its help it became possible to directly set the section nesting level (by manipulating the <section> tags in each other). The structure of the text can now be clearly reflected in the nesting (hierarchy) of tags.


This also affected the header tags <h#> , because Now the nesting of sections is determined by the nesting of the <section> , then to indicate the name of the section - it was enough to use only one <h1> in the form: “ <section><h1> </h1> </section> ”.


I have been using it for a long time (since the very appearance of <section> ), but creating this article, I saw another advantage of using <section> .


A good section title should accurately reflect its essence, but there are times when it is necessary to hold (not disclose) the essence to the middle of the section. That is, such a section should first pretend to be “routine”, and in the middle create a “wow / wtf effect”. Logically, this is all one section, but if you reveal its name at the very beginning of the section, then the name itself will be a spoiler . Imagine a book (detective story), on the cover of which will be all the information about the “killer”.


Here the “ <section> ” tag “comes on the scene”. It allows you to determine the name of the section anywhere within itself, i.e. not necessarily at the very beginning. Example: “ <section> <h1> </h1> </section> ”. So, we can simultaneously save the logical structure of the text, and show the name of the section at the right time. You can even make the section title visually appear at its beginning, after the reader reaches a certain point (up to the <h1> in html).


Here are just more than 9 years of the <section> existence, browsers have not learned how to properly build the “HTML5 document outline” to ensure accessibility .


Why not learned? In a document with a complex structure, it is difficult * to determine from which tag (section, article, ...) the numbering of headings (h1, h2, h3, ...) should begin. Now imagine that the document itself is placed on a page like this (with many additional blocks that are not related to the document itself, but have headers), and h1 is used everywhere for headers. And if on one page not one document, but several? However, visually everything looks good ( sample document ).


* - in fact, it is not difficult, everything is described in the standard , but in reality it does not work (see the explanation below).


Why does visually look good? Here, thanks to the styles , additional information appeared - the correspondence between the section hierarchy and the levels of headings (h #). So maybe when building the “HTML5 document outline” should use the information from the CSS? To do this, you need to add an additional property in the CSS for the title element, indicating its level, for example:


 body>section>h2                                 { heading-level: 1; font-size: 1.8em;  } body>section>section>h2                         { heading-level: 2; font-size: 1.4em;  } body>section>section>section>h2                 { heading-level: 3; font-size: 1.17em; } body>section>section>section>section>h2        { heading-level: 4; font-size: 1em;   } body>section>section>section>section>section>h2 { heading-level: 5; font-size: 0.83em; } 


Or a more rigorous version - in one section it is allowed to use only one heading. In this case, the header level is set by the section itself:


 body>section                                { heading-level: 1; } body>section>section                        { heading-level: 2; } body>section>section>section                { heading-level: 3; } body>section>section>section>section        { heading-level: 4; } body>section>section>section>section>section { heading-level: 5; } 


, and it doesn't matter what the title tag will be used: h1 or h5.


However, if earlier to create a “ heading-level outline ” it was enough to have only markup (HTML), now you also need styles (CSS). Can it be limited to markup (HTML)? With this question we came close to the problem of the “heading-level outline” construction algorithm described in the standard. So, the problem is not in the algorithm itself, but in the fact that only a limited (fixed) set of tags can act as the “ sectioning root ” of an element. But people often have “non-standard desires”: “I want the article tag on my page with a list of articles to be a 'sectioning root' element”, “and I want an arbitrary section to become a 'sectioning root' element”. Previously, it was enough for them to use several h1 tags on the same page (and they did it). So it can make any section (tags: section, article, ...) become a “sectioning root” element, if the title in it is set using the h1 tag? ..



# First steps: “before modeling” / “brainstorming”


Leaflet

UFO flew and left this gap here ? The reverse side of the piece of paper from the previous article .


# Protocol details


First we define what we need to include in the protocol. On the example of LLTR Basic.


The basis of the LLTR is an iteration of statistics collection on multiple hosts during a network scan. There are many iterations in LLTR (> 1) , so the first thing to include in the protocol is the control of starting and stopping each iteration. If we take into account that there are too many hosts (> 1) , then the management will consist in informing all hosts of the start time of the iteration and the end time of the iteration in a certain way. That is, synchronize all the hosts.


Each iteration has its own unicast src host and unicast dst host, so the next thing to include is the assignment method for each iteration of unicast src and dst. That is, in each iteration, one of the hosts must be “aware” of itself as a unicast src host, the purpose of which is to send traffic to a unicast dst host.


And the last. Upon completion of all iterations, all collected statistics from all hosts must be sent to one host for processing. This host will analyze the collected statistics, and build the network topology.


Also, at this step, you can think about some details of the implementation (limitations) of the protocol. For example, we want a program using LLTR to work without root rights, and from user space (that is, without installing a special driver in the system), which means that LLTR should work, for example, on top of TCP and UDP.


All the rest did implement, they will determine themselves, in the process of creating a model. That is, of course, you can immediately think over everything to the smallest detail, but at the same time there is a risk of “slipping into a local optimum” and not noticing the “better” implementation. It is good when there are several models - if each implementation has its own model, then it will be possible to combine the models, and step by step come to a better implementation. Recalling the genetic algorithm . For example, in one implementation / model there may be a centralized control, in the other - decentralized, in the third - a combination of the best parts from the previous two options.


# Select network simulator


Now the time has come to decide on the network simulator, in which we will create models and set up experiments.


Basically, from the network simulator, we need the ability to implement “our” protocol. Not all simulators make it easy to do.


But the presence of OS emulators of real network equipment of “global brands”, on the contrary, is not necessary. Most likely, emulators will create many restrictions that will only interfere with the experiments.


The Evaluating Network Simulation Tools article (our requirements for the simulator were largely the same) and OMNeT ++ General 'Network' Simulation helped me with the choice of simulator.


# Installing OMNeT ++ and INET


Download OMNeT ++ 5.0 .


And since OMNeT ++ is just a “discrete event simulator”, you will also need INET , a library of network models (protocols and devices). Downloading INET 3.4.0 . In fact, it could be installed from the IDE , but I recommend to install it manually (later it will be clear why).


Installation in * nix and in Windows is not much different. I will continue on the example of Windows.


Unpack OMNeT ++ in% ProgramData% (C: \ ProgramData \), and open the INSTALL.txt file (C: \ ProgramData \ omnetpp-5.0 \ INSTALL.txt). It says that the detailed instructions are in “doc / InstallGuide.pdf”, further it is written that if you do not want to read it, then simply execute:

$. setenv
$ ./configure
$ make

But do not rush to do it!


First, notice the first command . setenv . setenv ”. There is no “ setenv ” file in the “omnetpp-5.0” directory (it was in version 5.0b1). It is not needed (for Windows), so just run “mingwenv.bat” (I advise you to see what it does before launching ... to avoid a rm ). At the end, the terminal will break away (mintty).


Secondly, I advise you to tweak the “configure.user” file a bit (if the parameter mentioned is commented out in the file, then it should be uncommented):



Why is it worth turning off?

If it is not explicitly used, then it is not needed (in theory). For details, see section 16.1, 16.3, and 16.3.2 of “Parallel Simulation Example” in “doc / InstallGuide.pdf”, or here .



Now in the terminal (mintty) you can do:


 ./configure && make clean MODE=release make MODE=release –j17 


Note : “ 17 ” should be replaced with the number of CPU + 1 cores, or 1.5 × cores.


Caution for the curious (build 64bit)

In the tools / win32 directory is MSYS2, its compiler packages can be updated:



And OMNeT ++ can be built under 64bit .


But OMNeT ++ may simply not come together with a newer version of GCC (this was the case with the first batch of the fifth version of OMNeT ++ - without editing the source code, it was normally assembled only with GCC 4.x). And to switch to 64bit will take even more effort. First you need to revise the compilation options ( fPIC , not needed? ). Then, if you scroll through the OMNeT ++ source, you will see that the long type is often used there instead of int32_t, size_t and ptrdiff_t (as well as uintptr_t and intptr_t) . What does it threaten with? In * nix to 64bit (LP64) the long size will be 64bit, and on Windows (LLP64) - 32bit (see data models ). You’ll have to replace long with size_t and ptrdiff_t, but even here you will have the pitfalls. For example, you can open “src / utils / opp_lcg32_seedtool.cc” and look at line 231 - index or you can leave 32bit (replaced by int32_t), or make 64bit and modify all bitmasks + descriptions + (maybe) some_logics. Therefore, part of the long variables will need to be left 32bit, and the other part to make 64bit. In general, for correct work, you need to do all the points from:



Moreover, the same must be done with numerous libraries for OMNeT ++ , for example, with INET.


In general, I warn you against trying to make a 64bit build of OMNeT ++ .


Under * nix, I also recommend using a 32bit build (at least with version 5.0 or less).


Perhaps, sometime, Andrey2008 will undertake to check the OMNeT ++ and INET codes ... For now, I suggest simply finding and viewing all the “ FIXME ” / “ Fix ” in the code .


PS The references to the fact that the OMNeT ++ code was checked with a static code analyzer are absent, but in the “ChangeLog” files of INET 3.4.0 you can find 70 mentions about the elimination of defects after scanning in Coverity.



OMNeT ++ uses Eclipse as an IDE. For convenience, you can create a shortcut on the IDE “% ProgramData% \ omnetpp-5.0 \ ide \ omnetpp.exe”, and place it in an easily accessible place. The “ide / jre /” directory contains the JRE v1.8.0_66-b18. If a compatible JRE / JDK is already installed in the system, then the “ide / jre /” directory can be safely deleted by replacing the symbolic link with the location of the system JRE.


When you first start, Eclipse offers to place the workspace in the “samples” directory, but it is better to place it in any other convenient directory outside “% ProgramData%”. The main thing is that only Latin letters (+ symbols) are used on the way to the new directory, and there are no spaces.


After the closure of Welcome, the IDE will offer to install INET (as was written above), and import the examples - discard both items.


Eclipse settings, JVM options, additional plugins and themes

JVM options . Add to the file “ide / omnetpp.ini” (any editor that understands LF line feed will be suitable for editing; notepad will not work), keeping the empty last line:


 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+AggressiveOpts -XX:+TieredCompilation -XX:CompileThreshold=100 

Eclipse tuning (un [7z] me)


To make Eclipse, such as in the picture - look inside the picture.



It's time to install INET. The “inet” directory from the previously downloaded archive (inet-3.4.0-src.tgz) needs to be moved to the workspace. There is an “INSTALL” file in the directory with a step-by-step installation description. You can use it (section “If you are using the IDE”), but just don’t build (Build) a project!


Import INET:


  1. In Eclipse, open: File> Import.
  2. Select: General / Existing Projects to the Workspace.
  3. As the “root directory”, select the workspace location.
  4. Make sure that the “Copy projects into workspace” option is turned off.
  5. After clicking on the “Finish” button, wait until the project is indexed (% of completion, see below, in the status bar - “ C / C ++ Indexer”).


Set up the project:



Before setting {A}, you need to correct one of the project files. In the file “inet / .oppfeatures” there is a line “ inet.examples.visualization ” you need to add an empty line after it in which to write “ inet.tutorials.visualization ”, preferably keeping the indent to the left (by analogy with other parameters “ nedPackages ” in the file ). If this is not done, then nothing bad will happen, just after setting in “Problems” (Alt + Shift + Q, X), errors associated with “ inet.tutorials.visualization ” will always hang. You can first make {A} , and look at the errors, and then correct the file “inet / .oppfeatures” - while Eclipse will warn about the integrity violation in the settings, and offer to proxy them (we agree to this).


Let's get started ( “Project Explorer” panel > “inet” project> context menu> Properties ):


  1. Section “OMNeT ++”> subsection “Project Features”
    1. {A} remove everything except:
      • TCP Common
      • TCP (INET)
      • IPv4 protocol
      • UDP protocol
      • Ethernet
    2. “Apply” button.
  2. Section “ / ++ Build”:
    1. “Manage Configurations ...” button > make active “gcc-release” {B} ;
    2. Select the “gcc-release [Active]” {B} configuration.
    3. Subsection “Tool Chain Editor”:
      1. as “Current builder”, select “GNU Make Builder” for both configurations: “gcc-debug” and “gcc-release” {C} , note : if you change “Current builder” in the future, you will have to reconfigure everything!
      2. “Apply” button.
    4. “Behavior” tab (back to the root of the “C / C ++ Build” section):
      1. set “Use parallel jobs” to N (as N, you can choose either the number of CPU cores + 1 or 1.5 × cores) - this will allow using all CPU cores to compile {D} (set up for “gcc-debug” and “gcc- release ”).
    5. “Build Settings” tab:
      1. disable “Use default build command”;
      2. replace “Build command” with “ make MODE=release CONFIGNAME=${ConfigName} -j17 ” (“ 17 ” replace with previous value in the line, ie with selected N) {E} , the same can be done for the configuration of “gcc-debug”, replacing in the line “ MODE=release ” with “ MODE=debug ”, after that do not forget to switch back to “gcc-release [Active]”.
    6. “Apply” button.
  3. Section “ / ++ General”:
    1. Subsection “Paths and Symbols”:
      1. “Includes” tab:
        1. Add button: add the “ ../src ” directory with the selected “Add to all configurations” and “Add to all languages” {G} - initially “ ../src ” is in the “GNU C ++ ” language , but at an indefinite moment , it can be erased from the list;
        2. “Apply” button, and check that “ ../src ” appeared in all languages ​​and configurations.
      2. “Symbols” tab:
        1. Add button: add the character “ __cplusplus ” with the value “ 201103L ” and selected “Add to all configurations” and “Add to all languages” - {F} for details ;
        2. “Apply” button, and check that in the “gcc-debug” configuration of “ __cplusplus ” the value is “ 201103L ”.
      3. “Source Location” tab:
        1. Check that there is one item in the list, and it points to “ /inet/src ” {G} , if there’s something else (for example, just “ /inet ”), then delete what you have and add (“Add Folder ... ”)“ /inet/src ”. Then the “Apply” button, and return to {A} , since all filters were erased when removed. By the way, “ /inet ” can actually be left - with him, too, everything is going fine, but it is better to narrow down to the original “ /inet/src ”.
    2. Subsection “Preprocessor Include Paths, Marcos etc.”> tab “Providers”:
      1. Select “CDT GCC Build-in Compiler Settings”:
        1. In the “Language Settings Provider Options” group, click on the “Workspace Settings” link:
          1. “Discovery” tab: again select “CDT GCC Build-in Compiler Settings”, and add “ -std=c++11 ” before “ ${FLAGS} ” in “Command to get compiler specs”, it should look something like this ` ${COMMAND} -std=c++11 ${FLAGS} -E -P -v -dD "${INPUTS}" ` {F} , more ${COMMAND} -std=c++11 ${FLAGS} -E -P -v -dD "${INPUTS}" here and here ;
          2. “Apply”, “Ok” button (close the window).
        2. move “CDT GCC Build-in Compiler Settings” above “CDT Managed Build System Entries” (for both configurations: “gcc-release” and “gcc-debug”) {F} , in more detail - after that we will lose the ability to override the “CDT GCC Build-in Compiler Settings ”via“ CDT Managed Build System Entries ”( “ C / C ++ General ”> “ Paths and Symbols ”> “ Symbols ”), can only be overridden by adding values ​​to“ CDT User Settings Entries ” in the “Entries” tab for each language separately (alternative: do not change the order, because in “CDT Managed Build System Entries” have already corrected the value of __cplusplus ”; do not change the order, delete all references to __cplusplus __cplusplus ” “CDT Managed Build System Entries”, , );
        3. “Apply”, , “Entries” “GNU C++ ” “CDT GCC Build-in Compiler Settings” ( [ ] “Show build-in values” ) “ __cplusplus=201103L ” ( ).
    3. “Indexer”:
      1. “Build configuration for indexer” “gcc-release” {B} ;
      2. “Apply”.


{E} . . , Eclipse , “configure.user” OMNeT++ (./configure). Eclipse g++ make. , , , . , “Build command” {E} “ --just-print ” “ --trace ”, , ( “Project Explorer” > “inet” > > “Clean Project” “Build Project”), “Console” (Alt+Shift+Q,C), ‑ “ g++ -c -std=c++11 -O2 -fpredictive-commoning -march=native -freorder-blocks-and-partition -pipe -DNDEBUG=1 
 ”. , .



( “Project Explorer” > “inet” > > Properties ):


  1. “/++ Build”:
    1. “Build Variables” (, “gcc-release [ Active ]”):
      1. “Add
”, “ CFLAGS ”, “String”, “ -O2 -fpredictive-commoning -march=native -freorder-blocks-and-partition -pipe ”;
      2. “Add
”, “ CXXFLAGS ”, “String”, “ -std=c++11 -O2 -fpredictive-commoning -march=native -freorder-blocks-and-partition -pipe ”;
      3. “Apply”.
    2. “Environment”:
      1. “Add
”, “ CFLAGS ”, “ ${CFLAGS} ”;
      2. “Add
”, “ CXXFLAGS ”, “ ${CXXFLAGS} ”;
      3. “Apply”.


, , g++ , “ --just-print ” “ --trace ”, Process Explorer . Process Explorer , “ -march=native ” “cc1plus.exe”.


, , INET! , “gcc-release” {B} , “ --just-print ” “ --trace ” {E} , . ( “Project Explorer” > “inet” > > “Clean Project” “Build Project”), “Console” (Alt+Shift+Q,C).


, Eclipse, “.cproject” “.settings” {BG} , : “.oppfeatures”, “.oppfeaturestate”, “.nedexclusions” – {A} .


, , .


#


Note : , – “doc” OMNeT++ INET. Simulation Manual User Guide, Stack Overflow ( stackoverflow.com, ). , , , , “” .


Note : , OMNeT++ INET, , INET GitHub. 3.4.0 ( , INET ).


INET, , . , ?


INET “Project Explorer”, “inet/src/inet/applications”, “ udpapp ” (UDP Application). UDP broadcast . , , , , “ UDPEchoApp ”. “UDPBasicApp”, “Basic”. “.cc”, “.h” “.ned” . , “.ned” , ( “parameters: ” ) .


. , ( inet/examples ) INET. , “broadcast” ( inet/examples/inet/broadcast )! “.cc”, “.h” “.ned”, “.ini” “.xml” . , :



, (“broadcast”) , .. . , , .


Note : Simulation Manual . , , ( RAM) . JS ‑ bookmark let . , Simulation Manual, ( ), ( target Simulation Manual). Bookmarklet . , , Simulation Manual , bookmarklet .


bookmarklet , ?

bookmarklet . . 5- . bookmarklet , .
⇒ bookmarklet – ; bookmarklet , ( 5- ) – .



#


“LLTR”, “src” “simulations”, “gcc-release” (File → New → OMNeT++ Project
):


New OMNeT++ project Wizard


“inet”, . , “gcc-debug” (.. “LLTR”), “inet”. : {A,B,G} “Project References”, “inet”.


#


, Wizard, , “package.ned” : “src”, “simulations”. – “ package lltr; ” “ package lltr.simulations; ” . .


INET, “inet/src” – “LLTR/src”, “inet/examples” – “LLTR/simulations”. “LLTR/simulations” “.ned” c Network , “LLTR/src” – ().


– INET , INET, , INET. , – INET.


, “.ned” “LLTR/src” ( “inet/src”), “ package lltr.simulations; ” “LLTR/simulations”. “package.ned” “LLTR/src” “LLTR/simulations”.


#


LLTR. “LLTR/simulations/omnetpp.ini”, ( Run > Run As > 1 OMNeT++ Simulation):


Run simulation from toolbar


Eclipse “simulations” . , : “LLTR/src/LLTR.exe” . , “LLTR.exe” , ( Project → Build Project), ( ).


“No network specified in the configuration.”, , “ network = lltr. Network ” “ [General] ” “omnetpp .ini ”, “ network Network {} ” “package .ned ”. ( “.ned” ), ( “.ini” ) ( Network – ) .


( Run > Run As > 1 OMNeT++ Simulation), () Network .


Note : ( Run > Run As > 1 OMNeT++ Simulation), ( Run > 1 simulations): , .. , , Eclipse .


Note : ( – a1_v0.1.0 (“a” – article) “ git checkout -b â€čmy_branchâ€ș tags/a1_v0.1.0 ”)


#


, :



Note : “article_#” , , , ( ), /.


“ ”? , GitHub , :



, , “ git checkout -b â€č my_branch â€ș tags/â€čtag_nameâ€ș ”.


, .. ? Pull Request, >:-), , , , ):


Git: History Control System flow


, , Pull Request .


Note : , : , ( “ ” () , ). “ -u ” , . , “a1_v0.1. 0 ”, “a1_v0.2. 0 ”, 
 – “a1_v0.1. 1 ”, “a1_v0.2. 1 ”, 
 , : “a1_v0.1. 2 ”, “a1_v0.2. 2 ”, 



Note : tutorial , “”, git git tag diff icon , git tag.


Note : git diff , , ( , / ) ( AST ), Java .


# (Link Layer Topology Reveal)



# −1:


“package.ned” ( “Design” ), :


Network editor


, broadcast :



“” ( ) Eth100M (: 100 Mbps; : 10 ). , 10 , , ? ( )


( “Source” ), (git tag a1_v0.2.0) diff . :


 package â€č<a href="https://omnetpp.org/doc/omnetpp/manual/#sec:ned-ref:packages"> </a>â€ș; //<a href="https://omnetpp.org/doc/omnetpp/manual/#sec:ned-ref:directory-structure"> </a> import â€č<a href="https://omnetpp.org/doc/omnetpp/manual/#sec:ned-lang:imports-and-name-resolution">  </a>â€ș; network â€č<a href="https://omnetpp.org/doc/omnetpp/manual/#sec:ned-lang:warmup:network">  </a>â€ș {   @display(â€č  , ,  â€ș);   <a href="https://omnetpp.org/doc/omnetpp/manual/#sec:ned-ref:submodules">submodules</a>:       â€č<a href="https://omnetpp.org/doc/omnetpp/manual/#sec:ned-lang:submodules"> </a>â€ș: â€č â€ș { @display(â€č  , , â€ș); }   <a href="https://omnetpp.org/doc/omnetpp/manual/#sec:ned-ref:connections">connections</a>:       â€č â€ș.â€č<a href="https://omnetpp.org/doc/omnetpp/manual/#sec:ned-lang:gates"> </a>â€ș <--> â€č  â€ș <--> â€č â€ș.â€č â€ș; } 


Warning : <a>...</a> – “” . , , , ( <strong>...</strong> , <em>...</em> ).



package â€č â€ș; //

import â€č â€ș;

network â€č â€ș
{
@display(â€č , , â€ș);
submodules :
â€č â€ș: â€č â€ș { @display(â€č , , â€ș); }
connections :
â€č â€ș.â€č â€ș <--> â€č â€ș <--> â€č â€ș.â€č â€ș;
}


“ ” (Gates) :


  1. Gates , , gate “ â€č â€ș.â€čgateâ€ș[â€čâ€ș] ”, – “ â€č â€ș.â€čgateâ€ș ++ ”.
  2. (: “ 
 <--> { delay = 100ms; } <--> 
 ”), / , ( broadcast : “ 
 <--> C <--> 
 ”), (: “ 
 <--> FastEthernet {per = 1e-6;} <--> 
 ”), 

  3. Gates ( : output / input ; : --> / <-- ), ( : inout ; : <--> ). , , “ $i ” “ $o ” .



Warning : 1 ⁄ 3 20 ( 504 “Gateway Time-out”). 1 ⁄ 3 . ( ):


     <a href="#set">: “<code>set: p=1.87548</code>”</a>      . 


:


     <a href="#set"><code>: “set: p=1.87548</code>”</a>      . 


, 3‑ . :


   , <a href="https://omnetpp.org/doc/omnetpp/manual/#sec:ned-ref:inout-gates">  “<strong><code>$i</code></strong>”  “<strong><code>$o</code></strong>”</a>. 


, . , , GitHub Pages:


→


Note : target Simulation Manual – bookmarklet ', . « →» , .


Note : , CSS JS – , 3 , GitHub Pages 2‑ ( HTML, , , , ‑). 3‑ – .


# / To be continued




DOI: 10.5281/zenodo.1407029

#


. . – . – .


')

Source: https://habr.com/ru/post/420327/


All Articles