Tuesday, December 20, 2016

Centos 7 Install Realtime kernel using yum

Wanted to try out an rt kernel for my asterisk box. One option is to build a patched kernel.. The other option I am trying out now is to install using the Cern repo. I am using a plain Centos 7 installation and not the Cern version. At the time of writing this I had to install an older version of tuned in order to successfully finish the process:
yum install http://ftp.ntua.gr/mirror/centos/7.2.1511/updates/x86_64/Packages/tuned-2.5.1-4.el7_2.6.noarch.rpm
Install the repo in /etc/yum.repos.d/Centos-RT.repo:
[rt]
name=CentOS-$releasever - RealTime
baseurl=http://linuxsoft.cern.ch/cern/centos/$releasever/rt/$basearch/
gpgcheck=1
enabled=1
protect=1
priority=10
gpgkey=http://linuxsoft.cern.ch/cern/centos/7/os/x86_64/RPM-GPG-KEY-cern
Finally yum groupinstall RT should install the rt kernel. Reboot to use. I am currently trying it on a VM and so far no issues.

Some initial tests:

RT Version (VM):
 
chrt -f 99 ./cyclictest -t1 -p 80 -i 10000 -n -l 100000
# /dev/cpu_dma_latency set to 0us
policy: fifo: loadavg: 0.12 0.16 0.10 1/120 10969

T: 0 (10960) P:80 I:10000 C:  16390 Min:      6 Act:   20 Avg:   70 Max:   12866

hdparm -t /dev/sda2
/dev/sda2:
Timing buffered disk reads: 976 MB in  3.07 seconds = 317.71 MB/sec

Normal Version (VM):
 
chrt -f 99 ./cyclictest -t1 -p 80 -i 10000 -n -l 100000
# /dev/cpu_dma_latency set to 0us
policy: fifo: loadavg: 0.95 0.37 0.14 1/108 10165

T: 0 ( 8828) P:80 I:10000 C:   4838 Min:      5 Act:  413 Avg:  210 Max:    7676

hdparm -t /dev/sda2
Timing buffered disk reads: 1014 MB in  3.01 seconds = 336.37 MB/sec

After repeating the VM tests, I concluded that the VM is not the proper way to test. I will try it on real hardware later and post the results.

Normal Version (E5140 - 2 Cores):
 
chrt -f 99 ./cyclictest -t1 -p 80 -i 10000 -n -l 100000
# /dev/cpu_dma_latency set to 0us
policy: fifo: loadavg: 0.10 0.04 0.05 1/332 9408

T: 0 ( 9339) P:80 I:10000 C:   6901 Min:      3 Act:    3 Avg:    6 Max:    4503
hdparm -t /dev/sda2
Timing buffered disk reads: 526 MB in  3.01 seconds = 175.04 MB/sec

Tuesday, August 2, 2016

Alcatel OneTouch L850V

This dongle is recognized out of the box under Centos 7. You get a usbX device. You need to run a dhcp client on the device or there is the option to set an address 192.168.2.[2-254] cause the dongle WUI has 192.168.2.1. There is a hidden menu to access and disable the dhcpd server  on the dongle so that you won't need to use dhcp client hooks to avoid your rooting table and dns settings getting changed.

http://192.168.2.1/index.html#settings/routerSetting.html



 

Tuesday, February 9, 2016

Compile deluged in Centos 7 x86_64

In a proper build environment:

yum install boost-devel libgeoip (not supported anymore)


Get the latest libtorrent (1.1.2 at the time). To build it use b2.

cd /usr/local/src/
mkdir deluge
cd deluge
wget https://github.com/arvidn/libtorrent/releases/download/libtorrent-1_1_2/libtorrent-rasterbar-1.1.2.tar.gz
tar -xvf  libtorrent-rasterbar-1.1.2.tar.gz
cd  libtorrent-rasterbar-1.1.2

Edit Jamfile and set all TORRENT_USE_ICONV from 0 to 1.

#build libtorrent
b2 toolset=gcc link=shared variant=release target-os=linux address-model=64 crypto=openssl
 # produces  bin/gcc-4.8.5/release/address-model-64/crypto-openssl/threading-multi/libtorrent.so.1.1.2

cp bin/gcc-4.8.5/release/address-model-64/crypto-openssl/threading-multi/libtorrent.so.1.1.2 /usr/local/lib
ldconfig

cd bindings/python/

#build python bindings
b2 toolset=gcc link=shared variant=release target-os=linux address-model=64 libtorrent-link=shared

# produces: bin/gcc-4.8.5/release/address-model-64/libtorrent-python-pic-on/visibility-hidden/libtorrent.so

# we need to set the this otherwise deluge setup will try to build libtorrent in a way that does not work
PYTHONPATH=/usr/local/src/deluge/libtorrent-rasterbar-1.0.8/bindings/python/bin/gcc-4.8.5/release/address-model-64/libtorrent-python-pic-on/visibility-hidden

export PYTHONPATH


cd /usr/local/src/deluge/
wget http://download.deluge-torrent.org/source/deluge-1.3.12.tar.bz2 # or get from git or whatever
 tar -xvf deluge-1.3.12.tar.bz2

cd deluge-1.3.12
ln -s  /usr/local/src/delug/libtorrent-rasterbar-1.0.8 libtorrent

python setup.py build
python setup.py install # or bdist if you wise and did that in a virtual environment etc

You need to copy libtorrent python binding somewhere (like under deluge in /usr/lib/python/site-packages/deluge-1.3.12/deluge) or set the PYTHONPATH in order for the module to be found in runtime.


Friday, May 1, 2015

Cygwin/X forwarding issues after upgrade

A quick note if you are using Cygwin/X with putty or an ssh client not running within the cygwin environment:

Since X server 1.17, by default the server does not listen for TCP/IP connections, only accepting local connections on a unix domain socket.

That's from the FAQ.

A solution is to create a shortcut to Xwin.exe (located in the bin directory of cygwin installation path) either to the desktop or task bar and edit the Target in the shortcut's properties to:

C:\cygwin64\bin\XWin.exe -multiwindow -listen tcp -silent-dup-error

The listen option is the one that resolves errors like "Cannot open display XX:0".

There is also a script which sets up more stuff, check the FAQ above.

Monday, March 9, 2015

Multicast communication between Arduino (Ethernet library W5100) and a Java application

Multicast is not supported by the Arduino Ethernet library but is supported by the underlying W5100 module. So to start off, this patch should be applied to the library (usually located in the arduino IDE directory under libraries\Ethernet\src).

Note that you may want to update the IP ranges below, I have used the 192.168.100.0/24 network for my tests and 239.100.100.100 multicast group.

Here is a modified version of the UDPSendReceive example:
/*
  UDPSendReceive.pde:
 This sketch receives Multicast UDP message strings, prints them to the serial port
 and sends an "acknowledge" string back to the group.

 created 21 Aug 2010
 by Michael Margolis
 modified 09 Mar 2015
 by Panos Gkikakis

 This code is in the public domain.
 */


#include <SPI.h>         // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <EthernetUdp.h>         // UDP library from: [email protected] 12/30/2008


// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};

// Arduino's IP
IPAddress ip(192, 168, 100, 177);

// Multicast group IP
IPAddress mip(239, 100, 100, 100);

// Port 
unsigned int localPort = 9999;      // local port to listen on

// buffers for receiving and sending data
char packetBuffer[50]; //buffer to hold incoming packet,
char  ReplyBuffer[] = "acknowledged";       // a string to send back
char  hiBuffer[] = "0:Client ready";       // a string to send back

int c = 0;
// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void setup() {
  // start the Ethernet and UDP:
  Ethernet.begin(mac, ip);
  Udp.beginMulti(mip, localPort);
  

  Serial.begin(9600);
  
}

void loop() {
  // if there's data available, read a packet
  int packetSize = Udp.parsePacket();
  int n = 0;
  if (packetSize)
  {
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    IPAddress remote = Udp.remoteIP();
    for (int i = 0; i < 4; i++)
    {
      Serial.print(remote[i], DEC);
      if (i < 3)
      {
        Serial.print(".");
      }
    }
    Serial.print(", port ");
    Serial.println(Udp.remotePort());

    // read the packet into packetBufffer
    n = Udp.read(packetBuffer, 50);
    packetBuffer[n] = 0;
    
    Serial.println("Contents:");
    Serial.println(packetBuffer);
  
    // send a reply, to the IP address and port that sent us the packet we received
    Udp.beginPacket(mip, Udp.remotePort());
    Udp.write(ReplyBuffer, sizeof(ReplyBuffer));
    Udp.endPacket();
  }
  
  if( c == 0 ) {
    hiBuffer[0] = (hiBuffer[0] > 56) ?  48 : (hiBuffer[0] + 1);
    Udp.beginPacket(mip, localPort);
    Udp.write(hiBuffer, sizeof(hiBuffer));
    Udp.endPacket(); 
    Serial.println(hiBuffer);
    c++;    
  } else if( c > 600) {
    c = -1;
  }
    
  c++;  
  delay(10);
}

And here is a corresponding "server" written in java (MLTestServer.java):

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MulticastSocket;
import java.net.InetAddress;
import java.net.DatagramPacket;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.concurrent.atomic.AtomicReference;

public class MLTestServer {

 
 public static void main(String[] args)  {
  
  String msg = "Server online. Keep 'em coming!\0";
  String myIP = "192.168.100.1";
  String multiAddress = "239.100.100.100";
  int port = 9999;
  byte[] buf = new byte[100];  
  ConsoleReader cr = new ConsoleReader();
  String ack = "acknowledged";
  
  try {
   new Thread(cr).start();
   InetAddress group = InetAddress.getByName(multiAddress);

   // Q: Why use two sockets one for sending and one for receiving?
   // A: There are issues when sending and receiving, namely some messages were not received. If you know why or if that's expected behavior pls let me know.   
   // Q: Why use the long version of MulticastSocket constructor and joinGroup?
   // A: We need to specify the Network interface to get reliable results on  multihomed hosts. 
   MulticastSocket s = new MulticastSocket(new InetSocketAddress(InetAddress.getByName(myIP),port));
   MulticastSocket r = new MulticastSocket(new InetSocketAddress(InetAddress.getByName(myIP),port));

   s.joinGroup(new InetSocketAddress(group,port), NetworkInterface.getByInetAddress(InetAddress.getByName(myIP)));
   r.joinGroup(new InetSocketAddress(group,port), NetworkInterface.getByInetAddress(InetAddress.getByName(myIP)));
   
   // say hello
   DatagramPacket hi = new DatagramPacket(msg.getBytes(), msg.length(),group, port);
   s.send(hi);
   
   System.out.println("Started server: IP " + s.getLocalAddress() + " port " + s.getLocalPort());
   System.out.println("\tMulticast: " + group.getAddress() + " port " + port);

   DatagramPacket recv = new DatagramPacket(buf, buf.length);
   // server loop
   r.setSoTimeout(5);
   while(!ConsoleReader.exit) {
    try { 
     java.util.Arrays.fill(buf, (byte) 0);
     r.receive(recv); 
    } catch(SocketTimeoutException te) {
     msg = cr.send.get();    
     if(msg != null && (msg.length() > 0)) {
      System.out.println("Sending: " + '"' + msg + '"');
      hi = new DatagramPacket(msg.getBytes(), msg.length(),group, port);
      cr.send.set("");
      s.send(hi);
     }     
     continue;
    }
    
    msg = new String(recv.getData());
    
    System.out.println("Message from: " + recv.getAddress() + ":" + recv.getPort() +  ":\n" + msg);  
    
    
   }
   s.leaveGroup(group);
   r.leaveGroup(group);
   s.close();
   r.close();
   
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  
  
 }

}

// thread to read console input 
class ConsoleReader implements Runnable {

 public static boolean exit = false;
 public AtomicReference<String> send = new AtomicReference<String>();
 
 public void run() {
  String cmd;
  BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
  System.out.println("Commands:\t\nsend msg: sends a message (msg) to clients\t\nexit : end program");
  while(true) {
   try {
    cmd = console.readLine();
    if(cmd.compareToIgnoreCase("exit") == 0) {
     break;
    } else if (cmd.toLowerCase().startsWith("send ")) {
     this.send.set(cmd.substring(5) + "\0");
    } else {
     System.out.println("Unknown command");
    }
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    break;
   }
    
  }
  ConsoleReader.exit = true;
 }

}

 The code should be self explanatory, I have included comments for some gotchas. To compile the  java code simply run:

#compile
javac MLTestServer.java
#run

java -cp . MLTestServer

assuming off course javac and java is in the PATH.