<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[XYS's WORK]]></title><description><![CDATA[SDN, IoT, NFV, Next Generation Network]]></description><link>http://xuyansen.work/</link><generator>Ghost 0.6</generator><lastBuildDate>Sun, 16 May 2021 17:49:37 GMT</lastBuildDate><atom:link href="http://xuyansen.work/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Solve xcrun: error: invalid active developer path when using git on macOS High Sierra]]></title><description><![CDATA[Solve (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun]]></description><link>http://xuyansen.work/solve-missing-xcrun/</link><guid isPermaLink="false">e487d18d-b73e-46f9-b7f5-30f16fdbb9f8</guid><category><![CDATA[git]]></category><category><![CDATA[macos]]></category><category><![CDATA[high sierra]]></category><dc:creator><![CDATA[xys]]></dc:creator><pubDate>Sun, 16 May 2021 13:19:37 GMT</pubDate><content:encoded><![CDATA[<p>After updating to macOS High Sierra, it may encounter following error when using git or other commands. </p>

<pre><code>xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun  
</code></pre>

<p>To solve this problem, in your terminal, run the following command to install xcode command line.  </p>

<pre><code>xcode-select --install  
</code></pre>

<p>References: <br>
<a href="https://developer.apple.com/xcode/features/">Xcode IDE</a></p>]]></content:encoded></item><item><title><![CDATA[Does ICN Need a New Search Engine?]]></title><description><![CDATA[<p>(This article is under editing) <br>
When a user requests for a content, the user needs to know where the content is in current IP-based network. DNS provides the resolution of name. By DNS, user does not have to remember the IP address of a provider. Search engine provides the searching</p>]]></description><link>http://xuyansen.work/does-icn-needs-a-new-search-engine/</link><guid isPermaLink="false">3e0b0c3e-cedc-44f3-9576-50f2eb093544</guid><dc:creator><![CDATA[xys]]></dc:creator><pubDate>Tue, 14 Aug 2018 08:56:01 GMT</pubDate><content:encoded><![CDATA[<p>(This article is under editing) <br>
When a user requests for a content, the user needs to know where the content is in current IP-based network. DNS provides the resolution of name. By DNS, user does not have to remember the IP address of a provider. Search engine provides the searching services of contents. The results of search engine are indexes of locations of contents, i.e. <contents: locations=""> </contents:></p>

<p>ICN indexes contents not in form of location, but naming. <br>
Contents are not stored in the provider's server, but everywhere. <br>
User does not have to care about the location of content, but only the contents themselves. By sending a request of content name, the network will provide the content without DNS to resolve the name. (may need but not resolve the locations).</p>

<p>The search engine currently cannot handle this kindle of searching, i.e., searching contents name and return a location of contents. <br>
And the network does not need DNS. ICN needs a new naming-based search engine to discovery contents. <br>
If contents are everywhere (at least, not centralized in provider's server), how the search engine should perform and what kind of results should return. <br>
What the user wants, when the user search a phase. </p>]]></content:encoded></item><item><title><![CDATA[Basic Linear Programming - Concept]]></title><description><![CDATA[<p>Linear programming is an extremely general technique, and its applications are limited mainly by our imaginations and our ingenuity. </p>

<p><strong>Linear Programming</strong> is:</p>

<blockquote>
  <p>"A method to allocate scarce resources to competing activities in an optimal manner when the problem can be expressed using a linear objective function and linear inequality constraints.</p></blockquote>]]></description><link>http://xuyansen.work/basic-linear-programming/</link><guid isPermaLink="false">ce8ba7db-17ae-45bd-8ca6-a3ef60579a36</guid><category><![CDATA[Linear Programming]]></category><dc:creator><![CDATA[xys]]></dc:creator><pubDate>Wed, 01 Feb 2017 04:34:20 GMT</pubDate><content:encoded><![CDATA[<p>Linear programming is an extremely general technique, and its applications are limited mainly by our imaginations and our ingenuity. </p>

<p><strong>Linear Programming</strong> is:</p>

<blockquote>
  <p>"A method to allocate scarce resources to competing activities in an optimal manner when the problem can be expressed using a linear objective function and linear inequality constraints."</p>
</blockquote>

<p>A linear program consists of: </p>

<ul>
<li>a set of variables   </li>
<li>a linear objective function   </li>
<li>a set of linear constraints   </li>
</ul>

<p><strong>Decision Variables</strong> <br>
The variables in a linear program are a set of quantities that <em>need to be determined</em> in order to solve the problem.  </p>

<p>The variables are sometimes called decision variables because the problem is to decide what value each variable should take. </p>

<p>Typically, the variables represent <em>the amount of a resource to use or the level of some activity</em>. </p>

<p><strong>Objective Function</strong> <br>
The objective of a linear programming problem will be to <em>maximize</em> or to <em>minimize</em> some numerical value.</p>

<p><strong>Constraints</strong> <br>
Constraints define the <em>possible values</em> the variables of a linear programming problem may take. They typically represent resource constraints, or the minimum or maximum level of some activity. </p>

<p><strong>Non-negativity Constraints</strong> <br>
For technical reasons, the variables of linear programs must always take non-negative values.  </p>

<p><strong>References</strong> <br>
<a href="https://www.courses.psu.edu/for/for466w_mem14/Ch11/HTML/Sec1/ch11sec1.htm">Linear Programming</a></p>]]></content:encoded></item><item><title><![CDATA[Using pip behind proxy]]></title><description><![CDATA[<p>sudo pip --proxy <proxy> install &lt; module ></proxy></p>]]></description><link>http://xuyansen.work/using-pip-behind-proxy/</link><guid isPermaLink="false">e2c2e229-4d55-4fbb-84ba-2c1442f00e0d</guid><category><![CDATA[Linux]]></category><category><![CDATA[python]]></category><dc:creator><![CDATA[xys]]></dc:creator><pubDate>Fri, 29 Jul 2016 14:18:07 GMT</pubDate><content:encoded><![CDATA[<p>sudo pip --proxy <proxy> install &lt; module ></proxy></p>]]></content:encoded></item><item><title><![CDATA[Install OpenCV on Raspberry Pi]]></title><description><![CDATA[<p>sudo apt-get update <br>
sudo apt-get install python python-dev <br>
sudo apt-get install python-numpy python-scipy python-matplotlib <br>
sudo apt-get install libopencv-dev <br>
sudo apt-get install python-opencv</p>]]></description><link>http://xuyansen.work/install-opencv-on-raspberry-pi/</link><guid isPermaLink="false">f77cf9d3-ada8-4b67-b3c5-25c8510bfe35</guid><category><![CDATA[Linux]]></category><category><![CDATA[Raspberry Pi]]></category><category><![CDATA[opencv]]></category><dc:creator><![CDATA[xys]]></dc:creator><pubDate>Fri, 01 Jul 2016 01:56:26 GMT</pubDate><content:encoded><![CDATA[<p>sudo apt-get update <br>
sudo apt-get install python python-dev <br>
sudo apt-get install python-numpy python-scipy python-matplotlib <br>
sudo apt-get install libopencv-dev <br>
sudo apt-get install python-opencv</p>]]></content:encoded></item><item><title><![CDATA[Set WiFi connection on Raspberry Pi via Command Line]]></title><description><![CDATA[<h6 id="scanandlistavailablewifinetworks">Scan and list available WiFi networks:</h6>

<pre><code>sudo iwlist wlan0 scan  
</code></pre>

<h6 id="configurewpa_supplicantconffile">Configure <code>wpa_supplicant.conf</code> file:</h6>

<pre><code>sudo vi /etc/wpa_supplicant/wpa_supplicant.conf  
network={  
    ssid="The_ESSID_from_earlier"
    psk="Your_wifi_password"
}
</code></pre>

<h6 id="restartwlan0orreboot">Restart wlan0 or reboot:</h6>

<p><code>sudo ifdown wlan0</code> and <code>sudo ifup wlan0</code>, or reboot your Raspberry Pi with</p>]]></description><link>http://xuyansen.work/set-wifi-connection-on-raspberry-pi-via-command-line/</link><guid isPermaLink="false">840e2d98-656b-4a2b-9de4-888df9509e64</guid><category><![CDATA[Linux]]></category><category><![CDATA[Raspberry Pi]]></category><dc:creator><![CDATA[xys]]></dc:creator><pubDate>Thu, 23 Jun 2016 02:04:56 GMT</pubDate><content:encoded><![CDATA[<h6 id="scanandlistavailablewifinetworks">Scan and list available WiFi networks:</h6>

<pre><code>sudo iwlist wlan0 scan  
</code></pre>

<h6 id="configurewpa_supplicantconffile">Configure <code>wpa_supplicant.conf</code> file:</h6>

<pre><code>sudo vi /etc/wpa_supplicant/wpa_supplicant.conf  
network={  
    ssid="The_ESSID_from_earlier"
    psk="Your_wifi_password"
}
</code></pre>

<h6 id="restartwlan0orreboot">Restart wlan0 or reboot:</h6>

<p><code>sudo ifdown wlan0</code> and <code>sudo ifup wlan0</code>, or reboot your Raspberry Pi with <code>sudo reboot</code>.</p>

<h6 id="reference">Reference:</h6>

<p><a href="https://www.raspberrypi.org/documentation/configuration/wireless/wireless-cli.md">Raspberry Pi Website</a></p>]]></content:encoded></item><item><title><![CDATA[hose 模型]]></title><description><![CDATA[<p>随着IP技术为(Virtual Private Network)VPN的提供了大容量的接入能力，终端用户之间能够建立动态的安全连接，导致VPN增长迅速，然而对VPN的终端(endpoint)数量的增长量和终端间通讯模式的预测很困难。为了让网络适应各种流量模型并且在网络入口和出口不超过期望的速率，文献[1]提出了一个网络抽象模型，称为hose modeling。其目的是为了保证终端的带宽。</p>

<p>Hose服务模型的实现： <br>
在hose模型中，VPN用户需要指定一些列的终端，以及终端到终端的性能保证。每一个终端到网络之间的连接可以认为是一个软管(hose), 并且包含：  </p>

<ol>
<li>从终端到网络的(到其他VPN终端的)聚合外出(outgoing)流量的容量(capacity)需求  </li>
<li>从网络到终端的(从其他VPN终端来的)聚合进入流量的容量需求。  </li>
<li>从软管接口(hose interface)角度来看的的聚合流量的性能保证</li>
</ol>

<p>举一个论文里的例子：
用户的四个网络A, B, C, D与服务提供网络连接，其中B, C, D与A之间的收发速度分别不超过3Mbps, B, C, D之间的收发速率不超过2Mbps, 则软管模型(</p>]]></description><link>http://xuyansen.work/hose-mo-xing/</link><guid isPermaLink="false">3c3c4b3f-69be-45ff-8b4b-ba77ec62a23a</guid><category><![CDATA[hose]]></category><category><![CDATA[network model]]></category><dc:creator><![CDATA[xys]]></dc:creator><pubDate>Tue, 12 Apr 2016 11:01:54 GMT</pubDate><content:encoded><![CDATA[<p>随着IP技术为(Virtual Private Network)VPN的提供了大容量的接入能力，终端用户之间能够建立动态的安全连接，导致VPN增长迅速，然而对VPN的终端(endpoint)数量的增长量和终端间通讯模式的预测很困难。为了让网络适应各种流量模型并且在网络入口和出口不超过期望的速率，文献[1]提出了一个网络抽象模型，称为hose modeling。其目的是为了保证终端的带宽。</p>

<p>Hose服务模型的实现： <br>
在hose模型中，VPN用户需要指定一些列的终端，以及终端到终端的性能保证。每一个终端到网络之间的连接可以认为是一个软管(hose), 并且包含：  </p>

<ol>
<li>从终端到网络的(到其他VPN终端的)聚合外出(outgoing)流量的容量(capacity)需求  </li>
<li>从网络到终端的(从其他VPN终端来的)聚合进入流量的容量需求。  </li>
<li>从软管接口(hose interface)角度来看的的聚合流量的性能保证</li>
</ol>

<p>举一个论文里的例子：
用户的四个网络A, B, C, D与服务提供网络连接，其中B, C, D与A之间的收发速度分别不超过3Mbps, B, C, D之间的收发速率不超过2Mbps, 则软管模型(hose model)可以有下面的图表示。 红色的代表软管。</p>

<p><img src="https://lh3.googleusercontent.com/g9TZtH02Y4mXLkijslR04Zz-2pIs_sblyGCvNFRp9-f0CSz4bqY21roNyu2kHoHSA23zx_SI3wsPwSm6rhvDSUVYsmDweWKfOz6jhdBo0XbFGkwdp3HRI5SD5FEm9Bf5jTWqDwiKPkAXph4-vtYXV7tuPN6-j_6rgMm5o9CjuyB9cCE9N6LzmBA2ctELxcFyMDSjff7VNeAcx7U9-qLTxUMU70gbsf9S2TzAIq6yANg5uOvybFPRRTqPlsXBp_478u5s3W1rLyL_gNLwSEMklDwnaBCW-2Yy_sTtM747X6EJNyl3_Rrw3G8oBuE6d9kDmFpqa7WvVkr0DSRMQDitcXTqZoZGh0tB1-RDt5zxp-z9DvuMBS4X8ArAbNQAS8lxTYhNbPhNo6u-LFlXb_3YJus9NJMy0dAejWrN6R-yCEvBk7MRSVPf5O-mphUavJx3fj2V0J_cYZPpXAeTc4zh7orYwKEmAurEDdRPwWWHG-yJGTf8UOth1GXPwOODlJoP_8JT1GWTneYdaFJltWv87e4F-ZDz59AgkbYzbNlp1-fiafHnm8eqZDho0-PqYmTrd2cXaOkHYdHL9xF9ubkjNgiIuxgl65uWAI_f1pyyKU24lH7ExGpi=w1303-h483-no" alt="hose model"></p>

<p>从用户的角度看，Hose的优点是：  </p>

<ol>
<li>规格简单，只需要指定每个软管终端的流进和流出速率  </li>
<li>灵活，从一个软管终端收发的数据可以随意地分配到提供与软管大小相符合的其他终端上  </li>
<li>复用增益，根据统计的复用增益，软管速率可以小于用户管道(custom-pipe)的聚合速率  </li>
<li>易于描述，软和的需求可以被很容易的描述出来因为每一个单独的源-目的地的流量的统计上的变量可以很容易的聚合到软管里。</li>
</ol>

<p>References <br>
1 N.G. Duffield, et al., "A flexible model for resource management in virtual private networks," ACM SIGCOMM Computer Communication Review. Vol. 29. No. 4. ACM, 1999.</p>]]></content:encoded></item><item><title><![CDATA[Install CCNx on Ubuntu 14.02]]></title><description><![CDATA[<p>Server: Ubuntu 14.02 <br>
CCNx 1.0 ?</p>

<ol>
<li>Download CCNx Sources from <a href="http://blogs.parc.com/ccnx/ccnx-downloads/">website</a>  </li>
<li><p>untar: <br>
<code>$tar -zxvf distillery-ccnx-absinthe-source-current.tgz</code> </p></li>
<li><p>Enter the ccnx directory <br>
<code>$cd distillery-cnnx</code></p></li>
<li><p>Create two directory for ccnx as follow: <br>
<code>/usr/local/ccnx/</code> <br>
<code>/usr/local/parc/</code></p></li>
<li>Install dependency:  </li>
</ol>

<pre><code>   $ sudo apt-get update
   $sudo apt-get install build-essential libssl-dev openssl libevent-dev autoconf automake</code></pre>]]></description><link>http://xuyansen.work/install-ccnx-on-ubuntu/</link><guid isPermaLink="false">3fc9cf1c-0878-4b7a-8e2c-a38d3484e901</guid><category><![CDATA[Linux]]></category><category><![CDATA[ccn]]></category><dc:creator><![CDATA[xys]]></dc:creator><pubDate>Sat, 30 Jan 2016 08:02:34 GMT</pubDate><content:encoded><![CDATA[<p>Server: Ubuntu 14.02 <br>
CCNx 1.0 ?</p>

<ol>
<li>Download CCNx Sources from <a href="http://blogs.parc.com/ccnx/ccnx-downloads/">website</a>  </li>
<li><p>untar: <br>
<code>$tar -zxvf distillery-ccnx-absinthe-source-current.tgz</code> </p></li>
<li><p>Enter the ccnx directory <br>
<code>$cd distillery-cnnx</code></p></li>
<li><p>Create two directory for ccnx as follow: <br>
<code>/usr/local/ccnx/</code> <br>
<code>/usr/local/parc/</code></p></li>
<li>Install dependency:  </li>
</ol>

<pre><code>   $ sudo apt-get update
   $sudo apt-get install build-essential libssl-dev openssl libevent-dev autoconf automake libtool python
   $sudo apt-get install uncrustify doxygen
</code></pre>

<p>
  6.  <code>$make</code> <br>
 There should be no error</p>

<p>References: <br>
<a href="http://blogs.parc.com/ccnx/ccnx-downloads/">CCNx Downloads</a></p>]]></content:encoded></item><item><title><![CDATA[Add delay on packet using TC]]></title><description><![CDATA[<blockquote>
  <p>netem provides Network Emulation functionality for testing protocols by emulating the properties of wide area networks. The current version emulates variable delay, loss, duplication and re-ordering.</p>
</blockquote>

<p>TC(Traffic Control) is a Linux command to configure the Linux kernel's Network scheduler to show and manipulate Network traffic control settings. </p>

<p>Traffic Control</p>]]></description><link>http://xuyansen.work/tc/</link><guid isPermaLink="false">5e4d6b41-fa20-4d88-af52-ba60e1379162</guid><dc:creator><![CDATA[xys]]></dc:creator><pubDate>Thu, 05 Nov 2015 11:28:43 GMT</pubDate><content:encoded><![CDATA[<blockquote>
  <p>netem provides Network Emulation functionality for testing protocols by emulating the properties of wide area networks. The current version emulates variable delay, loss, duplication and re-ordering.</p>
</blockquote>

<p>TC(Traffic Control) is a Linux command to configure the Linux kernel's Network scheduler to show and manipulate Network traffic control settings. </p>

<p>Traffic Control consists of the following: <br>
SHAPING <br>
SCHEDULING <br>
POLICING</p>

<p>Processing of traffic is controlled by three kinds of objects: qdiscs, classes and filters   </p>

<p>By issuing the following command, packets with source IP address 192.168.10.109/32 and source port 59734 and 52049 is delayed 2000ms on eth0 </p>

<pre><code>sudo tc qdisc add dev eth0 root handle 1: prio  
sudo tc qdisc add dev eth0 parent 1:3 handle 30: netem delay 2000ms  
sudo tc filter add dev eth0 protocol ip parent 1:0 prio 3  \  
      u32 match ip src 192.168.10.109/32 match ip sport 59734 0xffff flowid 1:3
sudo tc filter add dev eth0 protocol ip parent 1:0 prio 3 \  
      u32 match ip sport 52049 0xffff flowid 1:3
</code></pre>

<p>References: <br>
<a href="http://www.linuxfoundation.org/collaborate/workgroups/networking/netem">NETEM-LinuxFoundation</a> <br>
<a href="https://en.wikipedia.org/wiki/Tc_(Linux)">TC WIKI</a> <br>
<a href="http://linux.die.net/man/8/tc">Linux man page</a></p>]]></content:encoded></item><item><title><![CDATA[Iperf3 Command and Option]]></title><description><![CDATA[<blockquote>
  <p>Iperf is a commonly used network testing tool that can create Transmission Control Protocol (TCP) and User Datagram Protocol (UDP) data streams and measure the throughput of a network that is carrying them. </p>
</blockquote>

<h6 id="generaloptions">GENERAL OPTIONS</h6>

<p><code>-p --port n</code> <br>
The server port for the server to listen on and the client</p>]]></description><link>http://xuyansen.work/iperf3-command-and-option/</link><guid isPermaLink="false">6e2b69f2-fe10-4328-aef0-fa19f3a0f438</guid><category><![CDATA[Linux]]></category><dc:creator><![CDATA[xys]]></dc:creator><pubDate>Sun, 06 Sep 2015 04:33:41 GMT</pubDate><content:encoded><![CDATA[<blockquote>
  <p>Iperf is a commonly used network testing tool that can create Transmission Control Protocol (TCP) and User Datagram Protocol (UDP) data streams and measure the throughput of a network that is carrying them. </p>
</blockquote>

<h6 id="generaloptions">GENERAL OPTIONS</h6>

<p><code>-p --port n</code> <br>
The server port for the server to listen on and the client to connect to. This should be the same in both client and server. Default is 5201.  </p>

<p><code>-i --interval n</code> <br>
Sets the interval time in seconds between periodic bandwidth, jitter, and loss reports. If non-zero, a report is made every interval seconds of the bandwidth since the last report. If zero, no periodic reports are printed. Default is zero.</p>

<p><code>-F, --file name</code> <br>
<strong>client-side:</strong> read from the file and write to the network, instead of using random data; <br>
<strong>server-side:</strong> read from the network and write to the file, instead of throwing the data away.  </p>

<p><code>-A, --affinity n/n,m-F</code> <br>
Set the CPU affinity, if possible (Linux and FreeBSD only). On both the client and server you can set the local affinity by using the n form of this argument (where n is a CPU number). In addition, on the client side you can override the server’s affinity for just that one test, using the n,m form of argument. Note that when using this feature, a process will only be bound to a single CPU (as opposed to a set containing potentialy multiple CPUs).  </p>

<p><code>-B, --bind host</code> <br>
Bind to host, one of this machine's addresses. For the client this sets the outbound interface. For a server this sets the incoming interface. This is only useful on multihomed hosts, which have multiple network interfaces.</p>

<p><code>-V, --verbose</code> <br>
give more detailed output  </p>

<p><code>-J, --json</code> <br>
output in JSON format  </p>

<p><code>--logfile file</code> <br>
send output to a log file. (new in iPerf 3.1)  </p>

<p><code>--d, --debug</code> <br>
emit debugging output. Primarily (perhaps exclusively) of use to developers.  </p>

<p><code>-v, --version</code> <br>
Show version information and quit.  </p>

<p><code>-h, --help</code> <br>
Show a help synopsis and quit. </p>

<h6 id="serverspecificoptions">SERVER SPECIFIC OPTIONS</h6>

<p><code>-s, --server</code> <br>
Run iPerf in server mode. (This will only allow one iperf connection at a time)</p>

<p><code>-D, --daemon</code> <br>
Run the server in background as a <a href="https://en.wikipedia.org/wiki/Daemon_(computing)">daemon</a>. </p>

<p><code>-I, --pidfilefile</code> <br>
write a file with the process ID, most useful when running as a daemon. (new in iPerf 3.1)</p>

<h6 id="clientspecificoptions">CLIENT SPECIFIC OPTIONS</h6>

<p><code>-c, --client host</code> <br>
Run iPerf in client mode, connecting to an iPerf server running on host.  </p>

<p><code>--sctp</code> <br>
Use <a href="https://en.wikipedia.org/wiki/Stream_Control_Transmission_Protocol">SCTP</a> rather than TCP (Linux, FreeBSD and Solaris). (new in iPerf 3.1) </p>

<p><code>-u, --udp</code> <br>
Use UDP rather than TCP. See also the -b option.  </p>

<p><code>-b, --bandwidth n[KM]</code> <br>
Set target bandwidth to n bits/sec (default 1 Mbit/sec for UDP, unlimited for TCP). If there are multiple streams (-P flag), the bandwidth limit is applied separately to each stream. You can also add a ’/’ and a number to the bandwidth specifier. This is called "burst mode". It will send the given number of packets without pausing, even if that temporarily exceeds the specified bandwidth limit.</p>

<p><code>-t, --time n</code> <br>
The time in seconds to transmit for. iPerf normally works by repeatedly sending an array of len bytes for time seconds. Default is 10 seconds. See also the -l, -k and -n options. </p>

<p><code>-n, --num n[KM]</code> <br>
The number of buffers to transmit. Normally, iPerf sends for 10 seconds. The -n option overrides this and sends an array of len bytes num times, no matter how long that takes. See also the -l, -k and -t options. </p>

<p><code>-k, --blockcount n[KM]</code> <br>
The number of blocks (packets) to transmit. (instead of -t or -n) See also the -t, -l and -n options.  </p>

<p><code>-l, --length n[KM]</code> <br>
The length of buffers to read or write. iPerf works by writing an array of len bytes a number of times. Default is 128 KB for TCP, 8 KB for UDP. See also the -n, -k and -t options.  </p>

<p><code>-P, --parallel n</code> <br>
The number of simultaneous connections to make to the server. Default is 1.  </p>

<p><code>-R, --reverse</code> <br>
Run in reverse mode (server sends, client receives).  </p>

<p><code>-w, --window n[KM]</code> <br>
Sets the socket buffer sizes to the specified value. For TCP, this sets the TCP window size. (this gets sent to the server and used on that side too)  </p>

<p><code>-M, --set-mss n</code> <br>
Attempt to set the TCP maximum segment size (MSS). The MSS is usually the MTU - 40 bytes for the TCP/IP header. For ethernet, the MSS is 1460 bytes (1500 byte MTU).  </p>

<p><code>-N, --no-delay</code> <br>
Set the TCP no delay option, disabling Nagle's algorithm. Normally this is only disabled for interactive applications like telnet.  </p>

<p><code>-4, --version4</code> <br>
only use IPv4.  </p>

<p><code>-6, --version4</code> <br>
only use IPv6.  </p>

<p><code>-S, --tos n</code> <br>
The type-of-service for outgoing packets. (Many routers ignore the TOS field.) You may specify the value in hex with a '0x' prefix, in octal with a '0' prefix, or in decimal. For example, '0x10' hex = '020' octal = '16' decimal. The TOS numbers specified in RFC 1349 are: </p>

<pre><code>IPTOS_LOWDELAY     minimize delay        0x10
IPTOS_THROUGHPUT   maximize throughput   0x08
IPTOS_RELIABILITY  maximize reliability  0x04
IPTOS_LOWCOST      minimize cost         0x02
</code></pre>

<p><code>-L, --flowlabel n</code> <br>
Set the IPv6 flow label (currently only supported on Linux).  </p>

<p><code>-Z, --zerocopy</code> <br>
Use a "zero copy" method of sending data, such as sendfile(2), instead of the usual write(2). This uses much less CPU.  </p>

<p><code>-O, --omit n</code> <br>
Omit the first n seconds of the test, to skip past the TCP TCP <a href="https://en.wikipedia.org/wiki/Slow-start">slowstart</a> period.  </p>

<p><code>-T, --title str</code> <br>
Prefix every output line with this string.  </p>

<p><code>-C, --linux-congestion algo</code> <br>
Set the <a href="https://en.wikipedia.org/wiki/TCP_congestion-avoidance_algorithm">congestion control algorithm</a> (Linux only for iPerf 3.0, Linux and FreeBSD for iPerf 3.1).  </p>

<p>Reference: <br>
<a href="https://iperf.fr/">Iperf</a></p>]]></content:encoded></item><item><title><![CDATA[Find Shortest Path in POX with NetworkX]]></title><description><![CDATA[<p>In the previous post <a href="http://xuyansen.work/install-networkx/">Install NetworkX</a>, I have introduced what is NetworkX and how to install NetworkX. This post shows how to apply NetworkX in POX to find a shortest path based on the topology mentioned in previous post <a href="http://xuyansen.work/crea/">Create a custom topology in Mininet (2)</a>.</p>

<p>This module first gets</p>]]></description><link>http://xuyansen.work/apply-networkx-in-pox/</link><guid isPermaLink="false">ea74976d-79a9-4192-94d4-7fde4dd0fcaf</guid><category><![CDATA[POX]]></category><category><![CDATA[SDN]]></category><category><![CDATA[NetworkX]]></category><category><![CDATA[ShortestPath]]></category><dc:creator><![CDATA[xys]]></dc:creator><pubDate>Mon, 03 Aug 2015 10:54:57 GMT</pubDate><content:encoded><![CDATA[<p>In the previous post <a href="http://xuyansen.work/install-networkx/">Install NetworkX</a>, I have introduced what is NetworkX and how to install NetworkX. This post shows how to apply NetworkX in POX to find a shortest path based on the topology mentioned in previous post <a href="http://xuyansen.work/crea/">Create a custom topology in Mininet (2)</a>.</p>

<p>This module first gets network's graph by using <code>openflow.discovery</code> module mentioned in <a href="http://xuyansen.work/discovery-topology-in-mininet/">Discovery Topology in POX</a>. The discovery module raises linkEvent if any link between two switches is added or removed. Then, this link is added to (or removed from) the network's graph. After controller got the network's graph, it calls <code>nx.shortest_path</code> to find the shortest path between host1 and host2.</p>

<pre><code>from pox.core import core  
import pox.openflow.libopenflow_01 as of  
from pox.lib.revent import *  
from pox.lib.recoco import Timer  
from collections import defaultdict  
from pox.openflow.discovery import Discovery  
from pox.lib.util import dpid_to_str  
import time  
import networkx as nx


class topoDiscovery(EventMixin):  
    G = nx.Graph()
    def __init__(self):
        def startup():
            core.openflow.addListeners(self, priority = 0)
            core.openflow_discovery.addListeners(self)
        core.call_when_ready(startup, ('openflow','openflow_discovery'))
        print "init completed"
    def _handle_LinkEvent(self, event):
        l = event.link
        sw1 = l.dpid1
        sw2 = l.dpid2
        pt1 = l.port1
        pt2 = l.port2
        self.G.add_node( sw1 )
        self.G.add_node( sw2 )
        if event.added:
            self.G.add_edge(sw1,sw2)
        if event.removed:
            try:
                self.G.remove_edge(sw1,sw2)
            except:
                print "remove edge error"
        print 'link added is %s'%event.added
        print 'link removed is %s' %event.removed
        print 'switch1 %d' %l.dpid1
        print 'port1 %d' %l.port1
        print 'switch2 %d' %l.dpid2
        print 'port2 %d' %l.port2
        print self.G.edges()

        try:
            print nx.shortest_path(self.G,1,6)
        except:
            print "no such Graph"
def launch():  
    core.registerNew(topoDiscovery)
</code></pre>

<p>run topoDiscovery and openflow.discovery  </p>

<pre><code>sudo ./pox/pox.py topoDiscovery openflow.discovery
</code></pre>

<p>Shortest path is shown as following:  </p>

<pre><code>[1, 2, 3, 6]
</code></pre>

<p>References: <br>
<a href="http://xuyansen.work/install-networkx/">Install NetworkX</a> <br>
<a href="http://xuyansen.work/discovery-topology-in-mininet/">Discovery Topology in POX</a></p>]]></content:encoded></item><item><title><![CDATA[Get Table Statistics Information In POX]]></title><description><![CDATA[<p>Monitoring table statistics is needed to evaluate a method whether it costs too much switch's resources or make a comparison between two methods. This post is shown how to get table statistics information such as active entries in switch. </p>

<p>Controller can query about datapath's current state using the <code>OFPT_STATS_</code></p>]]></description><link>http://xuyansen.work/get-flow-table-information-in-pox/</link><guid isPermaLink="false">1d7c7d87-ac99-4504-8f0d-9cf957567dd9</guid><category><![CDATA[POX]]></category><category><![CDATA[SDN]]></category><category><![CDATA[OPENFLOW]]></category><dc:creator><![CDATA[xys]]></dc:creator><pubDate>Sun, 02 Aug 2015 08:34:39 GMT</pubDate><content:encoded><![CDATA[<p>Monitoring table statistics is needed to evaluate a method whether it costs too much switch's resources or make a comparison between two methods. This post is shown how to get table statistics information such as active entries in switch. </p>

<p>Controller can query about datapath's current state using the <code>OFPT_STATS_REQEST</code> message. The structure of <code>OFPT_STATS_REQUEST</code> message is shown as following:  </p>

<pre><code>struct ofp_stats_request {  
    struct ofp_header header;
    uint16_t type; /* One of the OFPST_* constants. */
    uint16_t flags; /* OFPSF_REQ_* flags (none yet defined). */
    uint8_t body[0]; /* Body of the request. */
};
OFP_ASSERT(sizeof(struct ofp_stats_request) == 12);
</code></pre>

<p>The switch responds with one or more OFPT_STATS_REPLY messages:  </p>

<pre><code>struct ofp_stats_reply {  
    struct ofp_header header;
    uint16_t type; /* One of the OFPST_* constants. */
    uint16_t flags; /* OFPSF_REPLY_* flags. */
    uint8_t body[0]; /* Body of the reply. */
};
OFP_ASSERT(sizeof(struct ofp_stats_reply) == 12);
</code></pre>

<p>In both the request and response, the type field specifies the kind of information being passed and determines how the body field is interpreted:  </p>

<pre><code>enum ofp_stats_types {  
/* Description of this OpenFlow switch.
* The request body is empty.
* The reply body is struct ofp_desc_stats. */
OFPST_DESC,  
/* Individual flow statistics.
* The request body is struct ofp_flow_stats_request.
* The reply body is an array of struct ofp_flow_stats. */
OFPST_FLOW,  
/* Aggregate flow statistics.
* The request body is struct ofp_aggregate_stats_request.
* The reply body is struct ofp_aggregate_stats_reply. */
OFPST_AGGREGATE,  
/* Flow table statistics.
* The request body is empty.
* The reply body is an array of struct ofp_table_stats. */
OFPST_TABLE,  
/* Physical port statistics.
* The request body is struct ofp_port_stats_request.
* The reply body is an array of struct ofp_port_stats. */
OFPST_PORT,  
/* Queue statistics for a port
* The request body defines the port
* The reply body is an array of struct ofp_queue_stats */
OFPST_QUEUE,  
/* Vendor extension.
* The request and reply bodies begin with a 32-bit vendor ID, which takes
* the same form as in "struct ofp_vendor_header". The request and reply
* bodies are otherwise vendor-defined. */
OFPST_VENDOR = 0xffff  
};
</code></pre>

<p>Since we want to get the table statistics information from switch, we need to send  <code>OFPT_STATS_REQUEST</code> packet with type field <code>OFPST_TABLE</code>.</p>

<p>The body of the reply consists of an array of the following:  </p>

<pre><code>/* Body of reply to OFPST_TABLE request. */
    struct ofp_table_stats {
    uint8_t table_id; /* Identifier of table. Lower numbered tables are consulted first. */
    uint8_t pad[3]; /* Align to 32-bits. */
    char name[OFP_MAX_TABLE_NAME_LEN];
    uint32_t wildcards; /* Bitmap of OFPFW_* wildcards that are supported by the table. */
    uint32_t max_entries; /* Max number of entries supported. */
    uint32_t active_count; /* Number of active entries. */
    uint64_t lookup_count; /* Number of packets looked up in table. */
    uint64_t matched_count; /* Number of packets that hit table. */
};
OFP_ASSERT(sizeof(struct ofp_table_stats) == 64);  
</code></pre>

<p>According to the body of reply message, following information about flow table in switch can be obtained.  </p>

<pre><code>Max number of entries supported  
Number of active entries  
Number of packets looked up in table  
Number of packets that hit table  
</code></pre>

<p>The following code is an example for monitoring active entries in switches based on the topology mentioned in <a href="http://xuyansen.work/crea/">Create a custom topology in Mininet (2)</a>.</p>

<pre><code>from pox.core import core  
import pox.openflow.libopenflow_01 as of  
from pox.lib.revent import *  
from pox.lib.recoco import Timer  
from collections import defaultdict  
from pox.openflow.discovery import Discovery  
from pox.lib.util import dpid_to_str  
import time

class tableStats(EventMixin):  
  def __init__(self,interval = 10):
    self.tableActiveCount = {}
    self.interval = interval
    core.openflow.addListeners(self)
  def _handle_ConnectionUp(self,event):
    print "Switch %s has connected" %event.dpid
    self.sendTableStatsRequest(event)
  def _handle_TableStatsReceived(self,event):
    sw = 's%s'%event.dpid
    self.tableActiveCount[sw] = event.stats[0].active_count
    print "TableStatsReceived"
    print self.tableActiveCount
    Timer(self.interval, self.sendTableStatsRequest,args=[event])
  def sendTableStatsRequest(self, event):
    sr = of.ofp_stats_request()
    sr.type = of.OFPST_TABLE
    event.connection.send(sr)
    print "Send table stat message to Switch %s " %event.dpid

def launch(interval = '10'):  
  interval = int(interval)
  core.registerNew(tableStats,interval)
</code></pre>

<p>The above codes send table statistic request once controller and switches get connected. And when controller receives <code>TableStatsReceived</code> event, controller handles this event and sends table statistic request again in a interval (default is 10 seconds).</p>

<p>This program can be run by input </p>

<p><code>sudo ./pox/pox.py tableStat --interval=1</code>  </p>

<p>and the output is a dictionary like</p>

<p><code>{'s3': 0, 's2': 0, 's1': 0, 's6': 0, 's5': 0, 's4': 0}</code></p>

<p>References: <br>
<a href="https://www.opennetworking.org/images/stories/downloads/sdn-resources/onf-specifications/openflow/openflow-spec-v1.0.0.pdf">OpenFlow Switch Specification Version1.0.0</a> <br>
<a href="https://openflow.stanford.edu/display/ONL/POX+Wiki#POXWiki-ofp_stats_request-Requestingstatisticsfromswitches">POX WIKI - Requesting statistics from switches</a></p>]]></content:encoded></item><item><title><![CDATA[The Event System in POX]]></title><description><![CDATA[<p>POX is a publish/subscribe paradigm controller. In a publish/subscribe pattern, there are 3 parts -- publisher, subscriber and event. Publisher(or sender) can publish(or raise,source,dispatch)  an an event without any knowledge of subscriber(or receiver). A subscriber can subscribe(or listen to ) a publisher. A</p>]]></description><link>http://xuyansen.work/the-event-system-in-pox/</link><guid isPermaLink="false">c977d3ea-a0b0-4598-b2b5-9e1624d5538e</guid><category><![CDATA[POX]]></category><category><![CDATA[OPENFLOW]]></category><dc:creator><![CDATA[xys]]></dc:creator><pubDate>Thu, 30 Jul 2015 02:42:30 GMT</pubDate><content:encoded><![CDATA[<p>POX is a publish/subscribe paradigm controller. In a publish/subscribe pattern, there are 3 parts -- publisher, subscriber and event. Publisher(or sender) can publish(or raise,source,dispatch)  an an event without any knowledge of subscriber(or receiver). A subscriber can subscribe(or listen to ) a publisher. A publisher can be subscribed by multiple subscribers, and a subscriber can subscribe multiple publishers as well. POX works in publish/subscribe pattern and is an event-driven system.</p>

<p>In order to write a publish/subscribe program, we need to create 3 classes -- an event class, a publisher class, and a subscriber class. The relation between these 3 classes is shown as following figure. <br>
<img src="https://lh3.googleusercontent.com/SGwfNgfLx7HuEcFZVLcdQL66fBtIzwR-tODXidX00qg=w530-h163-no" alt="alt pub/sub">
<center>Figure 1 pub/sub pattern</center></p>

<h6 id="eventclass">Event Class</h6>

<p>Event Class can convey message from publisher to subscriber. In POX, events are subclasses of <code>revent.Event</code>. So to create an event, simply create a subclass of <code>Event</code>. You can add any extra attributes or methods you want.</p>

<p>First, create a python file named publisher.py  </p>

<pre><code>vi ./pox/ext/publisher.py  
</code></pre>

<p>In publisher.py, we first create an event for publisher raise. <br>
This event class is called <code>TestEvent</code>, it inherits from <code>Event</code> class. In its constructor(<strong>init</strong>), there are two arguments arg1 and arg2. When publisher raises this event, publisher can pass two arguments into this event.</p>

<pre><code>from pox.core import core  
from pox.lib.revent import *  
import pox  
import pox.openflow.libopenflow_01 as of

class TestEvent(Event):  
  def __init__(self,arg1,arg2):
    Event.__init__(self)
    print "TestEvent is initialed"
    self.par = arg1
    self.par2 = arg2
</code></pre>

<h6 id="publisherclass">Publisher Class</h6>

<p>Then we create a publisher in the same python file publisher.py</p>

<p>A publisher inherits from <em>revent.EventMixin</em> and declares which events it raises in a class-level variable called <code>_eventMixin_events = set([TestEvent,])</code>. Here publisher adds <em>TestEvent</em> into the eventMixin sets. Then this publisher can raise TestEvent which we created above.  </p>

<p>Then we define a function called <code>_handle_GoingUpEvent</code>. This function listens to core(as the code <code>self.listenTo(core)</code> in <code>__init__</code>), and handle the <em>GoingUpEvent</em> event raised by core. When publisher receive GoingUpEvent, publisher will listen to openflow (<code>self.listenTo(core.openflow)</code>).  </p>

<p>Next we define a function <em>publishEvent</em> which can raise the TestEvent. </p>

<p>In <em>publishEvent</em> function, <code>self.raiseEvent(Eventclass, **args)</code> can raise an Event. The first argument of <em>raiseEvent</em> is the event's class name, and follow the event's class name are arguments for events class. </p>

<p>Next we define a function <code>_handle_PacketIn</code> . This function can handle PacketIn event raised by openflow. When publisher receive <em>PacketIn</em> event, publisher call foo and foo raises the <em>TestEvent</em> event.</p>

<p>Last we define a function called <code>launch</code> which can register publisher into POX's core.  </p>

<pre><code>class Publisher(EventMixin):  
  """
  This is a Class for Publisher which can raise an event
  """
  _eventMixin_events = set([TestEvent,])
  def __init__(self):
    self.listenTo(core)
    print "Publisher is intialed\n"

  def _handle_GoingUpEvent(self, event):
    self.listenTo(core.openflow)
    print "this is in publisher, what is this for?\n"

  def publishEvent(self):
    print "publishEvent is called, will raise the test Event\n"
    self.raiseEvent(TestEvent,"firstPar","secondPar")
    print "foo raised event\n"

  def _handle_PacketIn(self,event):
    print "PacketIn event is raised,packetIn\n"
    self.publishEvent()
    return

def launch():  
  core.registerNew(Publisher)
</code></pre>

<h6 id="subsrciberclass">Subsrciber Class</h6>

<p>Next, we are going to create a Subscriber Class which can listen to Publisher and handle the <em>TestEvent</em> passed by Publisher.</p>

<p>We created a new python file called subscriber.py</p>

<p>In POX, a subscriber inherits from <em>revent.EventMixin</em>. </p>

<p>The Subscriber first listens to POX's core, and once <em>GoingUpEvent</em> is raised by core, the Subscriber listen to Publisher which has been registered into POX's core. </p>

<p>Then we define a function <code>_handle_TestEvent</code> which can handle <em>TestEvent</em> raised by Publisher and process event's arguments passed from Publisher.</p>

<p>Last function <code>launch</code> registers Subscriber into POX's core  </p>

<pre><code>vi ./pox/ext/subscriber.py  
</code></pre>

<pre><code>import pox  
import pox.openflow.libopenflow_01 as of  
from pox.core import core  
from pox.lib.revent import *

class Subscriber(EventMixin):  
  def __init__(self):
    self.listenTo(core)

  def _handle_GoingUpEvent (self, event):
    self.listenTo(core.Publisher)
    print "This is in subsriber, what is this for?\n"

  def _handle_TestEvent(self,event):
    print "Test Event is raised,I heard TestEvent\n"
    print "EventPar:", event.par
    print "EventPar:", event.par2
#    event.eventMethod()
    return

def launch():  
  core.registerNew(Subscriber)
</code></pre>

<p>So far, We have created a event class called <em>TestEvent</em>, a publisher class called <em>Publisher</em> and a subscribe class called <em>Subscriber</em>. And we added <em>TestEvent</em> into the <em>_eventMxin_events</em> set and created a function called <em>publishEvent</em> which can raise <em>TestEvent</em> and pass arguments into event.</p>

<p>In POX the function whose form is starting <em>_handle_eventName(self)</em>, is a function that handle the <em>eventName</em>. Such as <code>def _handle_GoingUpEvent(self, event)</code> can handle the event <em>GoingUpEvent</em> event raised by POX core, <code>def _handle_PacketIn(self, event)</code> can handle the event <em>PacketIn</em> raised by openflow, and <code>def _handle_TestEvent(self, event)</code> can handle the event <em>TestEvent</em> raised by Publisher.</p>

<p>The whole process of publish/subscribe system of above codes in POX is shown as following step:</p>

<ol>
<li>Publisher and Subscriber are registered into POX's core  </li>
<li>Publisher and Subscriber listen to POX's core  </li>
<li>Publisher and Subscriber receive an event called <em>GoingUpEvent</em> raised by POX's core  </li>
<li>Publisher listens to <em>core.openflow</em> when it received <em>GoingUpEvent</em>, whereas Subscriber listens to Publisher when it received <em>GoingUpEvent</em>  </li>
<li>Publisher receives a <em>PacketIn</em> event and then raise the <em>TestEvent</em> and pass two arguments  </li>
<li>Subscriber receives the <em>TestEvent</em> event and parses the two arguments passed with the event.</li>
</ol>

<p>References: <br>
[1] <a href="https://openflow.stanford.edu/display/ONL/POX+Wiki#POXWiki-TheEventSystem%3Apox.lib.revent">POX Wiki The Event System </a> <br>
[2] <a href="https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern">Wiki Publish–subscribe pattern</a> <br>
[3] <a href="http://richardzhao.me/?p=209">POX中创建新的Event</a></p>]]></content:encoded></item><item><title><![CDATA[Discovery Topology in POX]]></title><description><![CDATA[<h6 id="openflowdiscovery">openflow.discovery</h6>

<p>This component sends specially-crafted LLDP messages out of OpenFlow switches so that it can discover the network topology.  It raises events (which you can listen to) when links go up or down. <br>
More specifically, you can listen to LinkEvent events on core.openflow_discovery.  When a link is</p>]]></description><link>http://xuyansen.work/discovery-topology-in-mininet/</link><guid isPermaLink="false">47ee42e9-abd3-40ce-8c87-d94dd3cfe3e7</guid><category><![CDATA[POX]]></category><category><![CDATA[SDN]]></category><category><![CDATA[OPENFLOW]]></category><dc:creator><![CDATA[xys]]></dc:creator><pubDate>Mon, 27 Jul 2015 01:17:07 GMT</pubDate><content:encoded><![CDATA[<h6 id="openflowdiscovery">openflow.discovery</h6>

<p>This component sends specially-crafted LLDP messages out of OpenFlow switches so that it can discover the network topology.  It raises events (which you can listen to) when links go up or down. <br>
More specifically, you can listen to LinkEvent events on core.openflow_discovery.  When a link is detected, such an event is raised with the .added attribute set to True.  When a link is detected as having been removed or failed, the .removed attribute is set to True.  LinkEvent also has a .link attribute, which is a Link object, and a port_for_dpid(<code>&lt;dpid&gt;</code>) method (pass it the DPID of one end of the link and it will tell you the port used on that datapath). <br>
Link objects have the following attributes:  </p>

<table class="table table-bordered table-striped table-condensed">  
    <tr>
        <td>name</td>
        <td>value</td>
    </tr>
    <tr>
        <td>dpid1</td>
        <td>The DPID of one of the switches involved in the link</td>
    </tr>
    <tr>
        <td>dpid2</td>
        <td>The DPID of the other switch involved in the link</td>
    </tr>
    <tr>
        <td>end[0 or 1]</td>
        <td>The ends of the link as a tuple, i.e., end[0] = (dpid1,port1)</td>
    </tr>
    <tr>
        <td>port1</td>
        <td>The port on dpid1 involved in the link</td>
    </tr>
    <tr>
        <td>port2</td>
        <td>The port on dpid2</td>
    </tr>
    <tr>
        <td>uni</td>
        <td>A "unidirectional" version of the link.  This normalizes the order of the DPIDs and ports, allowing you to compare two links (which may be different directions of the same physical links).</td>
    </tr>
</table>

<p>A number of the other example components use discovery and can serve as demonstrations for using discovery.  Obvious possibilities are misc.gephi<em>topo and forwarding.l2</em>multi.</p>

<p>This example shows how to discovery topology created in <a href="http://xuyansen.work/crea/">previous post</a>. <br>
Component Discovery mentioned above is used to find discovery topology. <br>
This component can return the dpid and ports of switches involved in the link.</p>

<p>Create a python file in ~/pox/ext/topoDiscovery.py  </p>

<pre><code>vi ~/pox/ext/topoDiscovery.py  
</code></pre>

<pre><code>from pox.core import core  
import pox.openflow.libopenflow_01 as of  
from pox.lib.revent import *  
from pox.lib.recoco import Timer  
from collections import defaultdict  
from pox.openflow.discovery import Discovery  
from pox.lib.util import dpid_to_str  
import time

class topoDiscovery(EventMixin):

    def __init__(self):
        def startup():
            core.openflow.addListeners(self, priority = 0)
            core.openflow_discovery.addListeners(self)
        core.call_when_ready(startup, ('openflow','openflow_discovery'))
        print "init over"
    def _handle_LinkEvent(self, event):
        l = event.link
        sw1 = l.dpid1
        sw2 = l.dpid2
        pt1 = l.port1
        pt2 = l.port2

        print 'link added is %s'%event.added
        print 'link removed is %s' %event.removed
        print 'switch1 %d' %l.dpid1
        print 'port1 %d' %l.port1
        print 'switch2 %d' %l.dpid2
        print 'port2 %d' %l.port2

def launch():  
    core.registerNew(topoDiscovery)
</code></pre>

<p>First open a terminal and run topology file in mininet as previous post.  </p>

<pre><code>mininet@mininet-vm:~$ sudo ./type1.py  
</code></pre>

<p>and open a new terminal and run pox with above code and <code>openflow.discovery</code>  </p>

<pre><code>mininet@mininet-vm:~$ sudo ./pox/pox.py topoDiscovery openflow.discovery  
</code></pre>

<pre><code>mininet@mininet-vm:~$ sudo ./pox/pox.py topoDiscovery openflow.discovery  
POX 0.2.0 (carp) / Copyright 2011-2013 James McCauley, et al.  
init over  
INFO:core:POX 0.2.0 (carp) is up.  
INFO:openflow.of_01:[00-00-00-00-00-02 4] connected  
INFO:openflow.of_01:[00-00-00-00-00-04 2] connected  
INFO:openflow.of_01:[00-00-00-00-00-06 5] connected  
INFO:openflow.of_01:[00-00-00-00-00-03 3] connected  
INFO:openflow.of_01:[00-00-00-00-00-01 6] connected  
INFO:openflow.of_01:[00-00-00-00-00-05 1] connected  
INFO:openflow.discovery:link detected: 00-00-00-00-00-02.1 -&gt; 00-00-00-00-00-01.2  
link added is True  
link removed is False  
switch1 2  
port1 1  
switch2 1  
port2 2  
INFO:openflow.discovery:link detected: 00-00-00-00-00-02.2 -&gt; 00-00-00-00-00-03.2  
link added is True  
link removed is False  
switch1 2  
port1 2  
switch2 3  
port2 2  
INFO:openflow.discovery:link detected: 00-00-00-00-00-04.1 -&gt; 00-00-00-00-00-01.3  
link added is True  
link removed is False  
switch1 4  
port1 1  
switch2 1  
port2 3  
INFO:openflow.discovery:link detected: 00-00-00-00-00-04.2 -&gt; 00-00-00-00-00-05.1  
link added is True  
link removed is False  
switch1 4  
port1 2  
switch2 5  
port2 1  
INFO:openflow.discovery:link detected: 00-00-00-00-00-06.1 -&gt; 00-00-00-00-00-03.3  
link added is True  
link removed is False  
switch1 6  
port1 1  
switch2 3  
port2 3  
INFO:openflow.discovery:link detected: 00-00-00-00-00-03.3 -&gt; 00-00-00-00-00-06.1  
link added is True  
link removed is False  
switch1 3  
port1 3  
switch2 6  
port2 1  
INFO:openflow.discovery:link detected: 00-00-00-00-00-03.1 -&gt; 00-00-00-00-00-05.2  
link added is True  
link removed is False  
switch1 3  
port1 1  
switch2 5  
port2 2  
INFO:openflow.discovery:link detected: 00-00-00-00-00-03.2 -&gt; 00-00-00-00-00-02.2  
link added is True  
link removed is False  
switch1 3  
port1 2  
switch2 2  
port2 2  
INFO:openflow.discovery:link detected: 00-00-00-00-00-01.3 -&gt; 00-00-00-00-00-04.1  
link added is True  
link removed is False  
switch1 1  
port1 3  
switch2 4  
port2 1  
INFO:openflow.discovery:link detected: 00-00-00-00-00-01.2 -&gt; 00-00-00-00-00-02.1  
link added is True  
link removed is False  
switch1 1  
port1 2  
switch2 2  
port2 1  
INFO:openflow.discovery:link detected: 00-00-00-00-00-05.1 -&gt; 00-00-00-00-00-04.2  
link added is True  
link removed is False  
switch1 5  
port1 1  
switch2 4  
port2 2  
INFO:openflow.discovery:link detected: 00-00-00-00-00-05.2 -&gt; 00-00-00-00-00-03.1  
link added is True  
link removed is False  
switch1 5  
port1 2  
switch2 3  
port2 1  
</code></pre>

<p>And in Mininet, let link between s1 and s4 down  </p>

<pre><code>mininet&gt; link s1 s4 down  
</code></pre>

<p>wait a few seconds, pox outputs following information:  </p>

<pre><code>INFO:openflow.discovery:link timeout: 00-00-00-00-00-04.1 -&gt; 00-00-00-00-00-01.3  
link added is False  
link removed is True  
switch1 4  
port1 1  
switch2 1  
port2 3  
INFO:openflow.discovery:link timeout: 00-00-00-00-00-01.3 -&gt; 00-00-00-00-00-04.1  
link added is False  
link removed is True  
switch1 1  
port1 3  
switch2 4  
port2 1  
</code></pre>

<p>Next, let link between s1 and s4 up  </p>

<pre><code>mininet&gt; link s1 s4 up  
</code></pre>

<p>wait a few seconds, pox outputs following information:  </p>

<pre><code>INFO:openflow.discovery:link detected: 00-00-00-00-00-04.1 -&gt; 00-00-00-00-00-01.3  
link added is True  
link removed is False  
switch1 4  
port1 1  
switch2 1  
port2 3  
INFO:openflow.discovery:link detected: 00-00-00-00-00-01.3 -&gt; 00-00-00-00-00-04.1  
link added is True  
link removed is False  
switch1 1  
port1 3  
switch2 4  
port2 1  
</code></pre>

<p>References: <br>
<a href="https://openflow.stanford.edu/display/ONL/POX+Wiki#POXWiki-openflow.discovery">POX Wiki</a> <br>
<a href="http://xuyansen.work/crea/">Create a custom topology in Mininet (2)</a></p>]]></content:encoded></item><item><title><![CDATA[Create a custom topology in Mininet (2)]]></title><description><![CDATA[<p>Create a custom topology shown as figure 1 in Mininet</p>

<p><img src="https://lh3.googleusercontent.com/nNAznX03qZakcp0WNX7zzR7nz5O5Ke2vEvYlA7Xlxxc=w1033-h347-no" alt="alt topology">
<center>figure 1. topology</center></p>

<p>Create a new python file named type1.py</p>

<pre><code>#!/usr/bin/env python
"""Custom topology example
This example create a topology with 6 switches and 2 hosts.

     h1 --- s1 --- s2 --- s3 --- s6 --- h2</code></pre>]]></description><link>http://xuyansen.work/crea/</link><guid isPermaLink="false">db457fc9-215e-47ce-b152-6560f2c9dfc2</guid><category><![CDATA[SDN]]></category><category><![CDATA[Mininet]]></category><dc:creator><![CDATA[xys]]></dc:creator><pubDate>Mon, 27 Jul 2015 00:31:39 GMT</pubDate><content:encoded><![CDATA[<p>Create a custom topology shown as figure 1 in Mininet</p>

<p><img src="https://lh3.googleusercontent.com/nNAznX03qZakcp0WNX7zzR7nz5O5Ke2vEvYlA7Xlxxc=w1033-h347-no" alt="alt topology">
<center>figure 1. topology</center></p>

<p>Create a new python file named type1.py</p>

<pre><code>#!/usr/bin/env python
"""Custom topology example
This example create a topology with 6 switches and 2 hosts.

     h1 --- s1 --- s2 --- s3 --- s6 --- h2
             \            /
              \          /
               s4 --- s5

"""

from mininet.topo import Topo  
from mininet.net import Mininet  
from mininet.cli import CLI  
from mininet.log import setLogLevel, info  
class Type1( Topo ):  
    switchList = []
    def __init__( self):
        #Initialize topology
        Topo.__init__( self )
        # Add hosts and switches
        h1 = self.addHost( 'h1' )
        h2 = self.addHost( 'h2' )
        for i in range(1,7):
            self.switchList.append( self.addSwitch( 's' + str(i) ))
        # Add Links
        self.addLink( h1, self.switchList[0] )
        self.addLink( self.switchList[0], self.switchList[1] )
        self.addLink( self.switchList[0], self.switchList[3] )
        self.addLink( self.switchList[3], self.switchList[4] )
        self.addLink( self.switchList[4], self.switchList[2] )
        self.addLink( self.switchList[1], self.switchList[2] )
        self.addLink( self.switchList[2], self.switchList[5] )
        self.addLink( h2, self.switchList[5] )

def createTopo():  
    topo = Type1()
    net = Mininet( topo = topo )
    net.start()
    CLI(net)
    net.stop()

if __name__ == '__main__':  
    setLogLevel('info')
    createTopo()
</code></pre>

<p>This file is different from the file in "Create a custom topology in Mininet 1". <br>
This file can be executed directly by type in cli  </p>

<pre><code>mininet@mininet-vm:~$ sudo python type1.py  
</code></pre>]]></content:encoded></item></channel></rss>