logIt Log Around The Clock

application ARMv6 ARMv7 BeagleBoard certificate daemon device driver DNS embedded system emulator file system fuse GPIO image install-deinstall java java GUI job automation kernel local bin make-install managed node monitoring motif GUI OMAP3 OOP OSS OVCoreID php proxy python Raspberry Pi rootfs security shell script snmp socialmedia squid startup tagging template USB web-based wordpress Zabbix

SNMP: Mistake of Using Tabular OID in Practice

Recently, I retrieve rectifier-related SNMP data from Eltek’s Smartpack Controller. This one has the following rear type where we can connect to the ethernet plug (see the purple area).

Eltek Smartpack Controller type with SNMP Support

Eltek Smartpack Controller rear view (type that comes with SNMP support)

It is presumably in its default configuration and I can snmpwalk through its corporate specific OIDs (under 12148 tree) to find i.e. output voltage, current, battery temperature, etc. Doing it without translating against the MIB will retrieve all the values perfectly fine. However, I want to show you a mistake in practice related to how the MIB is written and put to place, which is a version 4 by the name of ELTEK-DISTRIBUTED-PLANTV4-MIB. It has tabular part as clipped in the following tree (see previous post on how to write such part in your own MIB):

            |     +--eltek(12148)
            |        |
            |        +--eltekDistributedPlantV4(9)
...
            |           |
            |           |     |
            |           |     +--rectifierStatusTable(2)
            |           |        |
            |           |        +--rectifierStatusEntry(1)
            |           |           |  Index: rectifierStatusID
            |           |           |
            |           |           +-- -R-- Integer32 rectifierStatusID(1)
            |           |           |        Range: 1..100
...
            |           |           +-- -R-- Integer32 rectifierStatusOutputVoltage(4)
            |           |           |        Range: 0..65535

Looking at the above rectifierStatusEntry branch, it marks a tabular entry expected to range from 1 to 100 as defined by rectifierStatusID. Hence, putting 0 as one of the output voltage index will confuse the OID reported by GET as

  1. belong to the scalar type (a misconception that is)
  2. belong to the tabular type but out of index range

GET against the MIB will return the following error

$ sudo snmpget -m +ELTEK-DISTRIBUTED-PLANTV4-MIB -v 1 -c public raddlex ELTEK-DISTRIBUTED-PLANTV4-MIB::rectifierStatusOutputCurrent.0
ELTEK-DISTRIBUTED-PLANTV4-MIB::rectifierStatusOutputCurrent.0: Unknown Object Identifier (Index out of range: 0 (rectifierStatusID))

while the item (output current) actually has value in it as found below

$ sudo snmpget -v 1 -c public raddlex .1.3.6.1.4.1.12148.9.5.5.2.1.3.0
SNMPv2-SMI::enterprises.12148.9.5.5.2.1.3.0 = INTEGER: 1

By this time the MIB is already the latest to be used with firmware version 4.3.

USB WiFi Stick on Beagleboard xM Using wpa_supplicant

One of the most popular USB WiFi sticks in Indonesian market is TP Link which is actually a Ralink wireless adapter (looking at its vendor ID code). Attaching it using wpa_supplicant without explicit driver assignment will return the following error lines

ioctl[SIOCSIWENCODEEXT]: Invalid argument
ioctl[SIOCSIWENCODEEXT]: Invalid argument
TL-WN321G-01.jpg

TP Link TL-WN321G USB WiFi Stick

Within minutes it will also crash the system with messages similar to:

kernel: [ 5645.279693] SysRq : HELP : loglevel(0-9) reBoot Crash terminate-all-tasks(E) memory-full-oom-kill(F) kill-all-tasks(I) thaw-filesystems(J) saK show-backtrace-all-active-cpus(L) show-memory-usage(M) nice-all-RT-tasks(N) powerOff show-registers(P) show-all-timers(Q) unRaw Sync show-task-states(T) Unmount ETM buffer dump show-blocked- tasks(W) dump-ftrace-buffer(Z)

The correct way to attach is

wpa_supplicant -B -Dnl80211 -iwlan0 -c/etc/wpa_supplicant.conf

The config file content is just like what the community help suggested. The stick with vendor & product ID of 148f:2573 has been part of the nl80211 development at Linux Wireless.

wpa_supplicant version is v0.7.3. Ubuntu version is 11.10 as described further in previous post.

Close Low Level Socket in Python

tags:

Important to do in socket programming is to close the socket. Python.org says

Close the socket. All future operations on the socket object will fail. The remote end will receive no more data (after queued data is flushed). Sockets are automatically closed when they are garbage-collected.

I implemented this low level networking interface for a server listening to remote command. The complete code can be found on Github, the following lines are just part to show when to close socket:

43
44
45
46
        clientSocket,address =s.accept()
        data = clientSocket.recv(1024)
        print "Receive command:"+data
        clientSocket.close()

What happened with the TCP state when the socket wasn’t closed: it stayed in CLOSE_WAIT state. The screenshot below shows a clip of the TCP conversation in Wireshark sniff and the netstat output:

Listening port state of a socket server written in Python

Compile USB Serial Modem Using option.c (Ubuntu on Beagleboard xM)

Despite possibility to use (1)

$ modprobe -v usbserial vendor=0x05c6 product=0x0015

or (2) usb-modeswitch, (3) Matthias Urlichs initially wrote option.c driver as a way to insert USB modem as kernel module.

This driver exists because the “normal” serial driver doesn’t work too well
with GSM modems. Issues:
- data loss — one single Receive URB is not nearly enough
- nonstandard flow (Option devices) control
- controlling the baud rate doesn’t make sense

Most modems will be successfully attached with this driver, appearing in one of the typical /dev/ttyUSB0 to /dev/ttyUSB2. The product ID 0x0015 for GSM modem compiled here is a Qualcomm (vendor ID 0x05c6) OEM modem I received from Embest DevKit8500D order. There are more than one form factor when searching for its images on Google. Closest one we have in Indonesia is ADVAN DT8-HT bundled in Telkomsel Flash.

qualcomm-05c6-0015-telkomsel-advan.jpg

Qualcomm 05c6:0015 from Indonesian operator

I’m compiling it for the Beagleboard xM Rev C running Ubuntu Oneiric (installed in this post). A quick look gives:

$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp.
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 005: ID 05c6:0015 Qualcomm, Inc.

The above 0x0015 product ID doesn’t exist inside option.c of linux kernel 3.0.0-12 source. Adding this to series of existing Qualcomm modems gives:

635
636
637
	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */
	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0015)}, /* Qualcomm no brand */

The include also needs usb-wwan.h from that kernel source. Copy them both under /usr/src/linux-headers-3.0.6-x3/drivers/usb/serial/. For other include files, install:

  1. linux-headers-3.0.0-12_3.0.0-12.20_all.deb
  2. linux-image-3.0.0-12-omap_3.0.0-12.20_armel.deb

and create this link as root

1
2
$ cd /usr/src/linux-headers-3.0.6-x3/include/
$ ln -s /usr/src/linux-headers-3.0.0-12/arch/arm/mach-versatile/include/mach mach

After removing the old one (pointed to build -> /build/buildd/linux-3.0), create a link inside /lib/modules/3.0.6-x3 named build pointing to:

build -> /usr/src/linux-headers-3.0.6-x3

Modify the original Makefile to contain only rule for option.o

obj-m			+= option.o

and then build the driver

$ make -C /lib/modules/3.0.6-x3/build/ M=/usr/src/linux-headers-3.0.6-x3/drivers/usb/serial/
make: Entering directory `/usr/src/linux-headers-3.0.6-x3'
  LD      /usr/src/linux-headers-3.0.6-x3/drivers/usb/serial/built-in.o
  CC [M]  /usr/src/linux-headers-3.0.6-x3/drivers/usb/serial/option.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /usr/src/linux-headers-3.0.6-x3/drivers/usb/serial/option.mod.o
  LD [M]  /usr/src/linux-headers-3.0.6-x3/drivers/usb/serial/option.ko
make: Leaving directory `/usr/src/linux-headers-3.0.6-x3`

Copy the build and deploy

$ cp /usr/src/linux-headers-3.0.6-x3/drivers/usb/serial/option.ko /lib/modules/3.0.6-x3/kernel/drivers/usb/serial/
$ depmod -a

Now syslog will show the following lines if the modem is inserted:

kernel:[ 4790.229888] usb 1-2.5: GSM modem (1-port) converter now attached to ttyUSB0
kernel:[ 4790.237121] option 1-2.5:1.0: GSM modem (1-port) converter detected
kernel:[ 4790.238250] usb 1-2.5: GSM modem (1-port) converter now attached to ttyUSB1
kernel:[ 4790.240142] option 1-2.5:1.1: GSM modem (1-port) converter detected
kernel:[ 4790.241210] usb 1-2.5: GSM modem (1-port) converter now attached to ttyUSB2
mtp-probe: checking bus 1, device 9: "/sys/devices/platform/usbhs-omap.0/ehci-omap.0/usb1/1-2/1-2.5"
mtp-probe: bus: 1, device: 9 was not an MTP device
kernel:[ 4791.227294] scsi 2:0:0:0: Direct-Access     Qualcomm MMC Storage      2.31 PQ: 0 ANSI: 2
kernel:[ 4791.232238] sd 2:0:0:0: Attached scsi generic sg0 type 0
kernel:[ 4791.246887] sd 2:0:0:0: [sda] Attached SCSI removable disk

Ubuntu on Beagleboard xM with Easycap Video Capture (Compiling Driver)

Attempt to run Ubuntu in BeagleBoard xM rev C board has taken me to try various options of kernel and release. The goal was to have both Ubuntu and widely-available Easycap as video input via the USB of this compact TI OMAP board. Porting Ubuntu would spare us some flexibility to try different alternatives of video processing and networking options for the stream. The easiest way initially was to run Ubuntu preinstalled image. I had two popular options immediately: 1) Ubuntu Port CD Image release 2) Robert C. Nelson custom image (rootfs). I started with the later first to see the board running at once. The latest found in http://rcn-ee.net/deb/rootfs/ was ubuntu-11.10-r0-minimal-armel.tar.xz which gave me Ubuntu 11.10 Oneiric with custom linux 3.0.3-x2 kernel.

Easycap USB Video-Audio Capture.jpg

Easycap USB Video-Audio Capture

It turned out that this custom kernel hadn’t been compiled without Easycap. We can compare that to my laptop running linux 2.6.38-10 where it was part of its kernel compilation:

[ubuntu-laptop]$ cat  /usr/src/linux-headers-2.6.38-10/.config | grep -i easy
CONFIG_EASYCAP=m

Compiling the whole thing using make menuconfig to change .config file and so on seemed too much. A more partial approach was to touch only relevant Makefile involved in building the driver. First we needed the kernel header files provided as linux-headers-3.0.6-x3_1.0oneiric_armel.deb and then source files for Easycap. As this was custom kernel, by guessing I found that it was closest to official linux 3.0.0-12.20 at launchpad, hence easycap source files were copied from it (the custom kernel might’ve been forked from this release as some random header files comparison to linux-headers-3.0.0-12-omap_3.0.0-12.20_armel returned no difference).

FYI Easycap linux driver is no longer developed separately as a SourceForge project, it has been part of drivers/staging in recent kernel releases (where you get dmesg like “module is from the staging directory, the quality is unknown, you have been warned” when inserting it). In the source we’ll find /linux-3.0/drivers/staging/easycap/ to be copied into /usr/src/linux-headers-3.0.6-x3/drivers/staging/easycap/ on the board.

After removing the old one (pointed to build -> /build/buildd/linux-3.0), I created a link inside /lib/modules/3.0.6-x3 named build pointing to:

build -> /usr/src/linux-headers-3.0.6-x3

then copied the Makefile from my laptop to replace original Easycap source with this content of rules:

obj-m	+= easycap.o
 
easycap-y	:= easycap_main.o easycap_low.o easycap_sound.o
easycap-y	+= easycap_ioctl.o easycap_settings.o
easycap-y	+= easycap_testcard.o
 
ccflags-y := -Wall
# Impose all or none of the following:
ccflags-y += -DEASYCAP_IS_VIDEODEV_CLIENT
ccflags-y += -DEASYCAP_NEEDS_V4L2_DEVICE_H
ccflags-y += -DEASYCAP_NEEDS_V4L2_FOPS
ccflags-y += -DEASYCAP_NEEDS_UNLOCKED_IOCTL

Compiling should work afterward:

$ make -C /lib/modules/3.0.6-x3/build/ M=/usr/src/linux-headers-3.0.6-x3/drivers/staging/easycap/
  LD      /usr/src/linux-headers-3.0.6-x3/drivers/staging/easycap/built-in.o
  CC [M]  /usr/src/linux-headers-3.0.6-x3/drivers/staging/easycap/easycap_main.o
  CC [M]  /usr/src/linux-headers-3.0.6-x3/drivers/staging/easycap/easycap_low.o
  CC [M]  /usr/src/linux-headers-3.0.6-x3/drivers/staging/easycap/easycap_sound.o
  CC [M]  /usr/src/linux-headers-3.0.6-x3/drivers/staging/easycap/easycap_ioctl.o
  CC [M]  /usr/src/linux-headers-3.0.6-x3/drivers/staging/easycap/easycap_settings.o
  CC [M]  /usr/src/linux-headers-3.0.6-x3/drivers/staging/easycap/easycap_testcard.o
  LD [M]  /usr/src/linux-headers-3.0.6-x3/drivers/staging/easycap/easycap.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /usr/src/linux-headers-3.0.6-x3/drivers/staging/easycap/easycap.mod.o
  LD [M]  /usr/src/linux-headers-3.0.6-x3/drivers/staging/easycap/easycap.ko
make: Leaving directory `/usr/src/linux-headers-3.0.6-x3'

I tried to insmod the easycap.ko built, but dmesg showed some error and no /dev/video0 created. There must be some other drivers that must be loaded first which I didn’t know in what sequence (i.e. v4l2-common etc.), hence I decided to just copy that under the /lib/modules/3.0.6-x3/kernel/drivers/staging/easycap, depmod -a, and reboot.

If you plug the Easycap while inspecting the syslog tail, there won’t be similar message as found in kernel 2.6.38-10. Instead, you’ll see:

kernel: [ 1377.696838] usb 1-2.3: new high speed USB device number 6 using ehci-omap
mtp-probe: checking bus 1, device 6: "/sys/devices/platform/usbhs-omap.0/ehci-omap.0/usb1/1-2/1-2.3"
mtp-probe: bus: 1, device: 6 was not an MTP device
kernel: [ 1378.052459] Linux video capture interface: v2.00
kernel: [ 1378.169006] Easycap version: 0.9.01
kernel: [ 1378.198944] usbcore: registered new interface driver snd-usb-audio
kernel: [ 1381.043853] easycap::0adjust_standard: selected standard: PAL_BGHIN
kernel: [ 1381.151245] easycap::0adjust_format: sought:    640x480,UYVY(0x59565955),1=field,0x00=std mask
kernel: [ 1381.151306] easycap::0adjust_format: sought:    V4L2_FIELD_NONE
kernel: [ 1381.151336] easycap::0adjust_format: actioning: 640x480 PAL_BGHIN_AT_640x480_FMT_UYVY-n
kernel: [ 1381.181488] easycap::0adjust_brightness: adjusting brightness to  0x7F
kernel: [ 1381.184478] easycap::0adjust_contrast: adjusting contrast to  0x3F
kernel: [ 1381.212768] easycap::0adjust_saturation: adjusting saturation to  0x2F
kernel: [ 1381.214599] easycap::0adjust_hue: adjusting hue to  0x00
kernel: [ 1381.219207] easycap::0easycap_usb_probe: registered with videodev: 0=minor
kernel: [ 1381.219238] easycap::0easycap_usb_probe: ends successfully for interface 0
kernel: [ 1381.219543] usbcore: registered new interface driver easycap
kernel: [ 1381.314453] easycap:: easycap_open: ==========OPEN=========
kernel: [ 1384.031188] easycap::0adjust_standard: selected standard: PAL_BGHIN
kernel: [ 1384.228759] easycap::0adjust_format: sought:    640x480,UYVY(0x59565955),1=field,0x00=std mask
kernel: [ 1384.228790] easycap::0adjust_format: sought:    V4L2_FIELD_NONE
kernel: [ 1384.228851] easycap::0adjust_format: actioning: 640x480 PAL_BGHIN_AT_640x480_FMT_UYVY-n
kernel: [ 1384.233489] easycap::0adjust_brightness: adjusting brightness to  0x7F
kernel: [ 1384.235198] easycap::0adjust_contrast: adjusting contrast to  0x3F
kernel: [ 1384.237884] easycap::0adjust_saturation: adjusting saturation to  0x2F
kernel: [ 1384.239501] easycap::0adjust_hue: adjusting hue to  0x00

Later I find out that newer image is available on the Robert’s site, but not sure which linux source I should use for the Easycap if I were to to use it. Anyway, before deciding to just go with this one I’ve tried various kernels. Here are list of images and their kernel versions (I wasn’t quite sure which one was running smoothly and which wasn’t):

  1. linux-2.6.35.9-l9 Ubuntu 10.04 Lucid: ubuntu-10.04.1-r4-minimal-armel.tar
  2. linux-3.1.4-x6 Ubuntu 11.10 Oneiric: ubuntu-11.10-r2-minimal-armel.tar.xz
  3. linux-3.1.4-x6 Ubuntu 11.04 Natty: ubuntu-11.04-r7-minimal-armel.tar.xz
  4. linux-2.6.38.2-d9 Ubuntu 10.10 Maverick: ubuntu-10.10-r6-minimal-armel.tar.xz

Hello World with JamVM Embedded JVM on Ubuntu ARM

While waiting for my BeagleBoard xM shipment, I was considering Java as one of the possible application platforms. Anyhow, the keyword “embedded Java ARM” landed me to the tiny JamVm. This JVM is said to be working with ARM Cortex A8 which can be emulated under QEMU running Ubuntu ARM. The fact that there had been already a Karmic image that work with QEMU would shorten the time.

A “Hello World” class to test the JVM will be:

class HelloWorldJamVM {
	public static void main(String[] args) {
		System.out.println("hello world");
	}
}

saved as HelloWorldJamVM.java. However, executing a “Hello World” requires longer steps than writing that class.

In order for the JamVM 1.5.4 to run on Ubuntu, we need (1) build-essential (certainly so) and (2) GCJ with dependency of (3) zlib1g-dev. It’s all available in the Karmic ARM repo. Another thing that we need is GNU Classpath 0.98.

Following the instruction, as root we can then configure, make, make install, make install-strip sources under jamvm-1.5.4 directory. Continue them with the classpath-0.98 sources by configuring as follow

./configure --disable-gtk-peer --disable-gconf-peer --disable-plugin --disable-Werror

and then make install as usual. The whole compiling will run slow for sure as QEMU emulates ARM far from nearing native processor performance in my case.

We can compile the above “Hello World” using GCJ with the command javac, which is actually linked to /usr/bin/gcj-wrapper-4.4.

javac HelloWorldJamVM.java

A HelloWorldJamVM.class bytecode file will appear and we can run this with JamVM

PATH=$PATH:/usr/local/jamvm/bin 
export PATH
jamvm HelloWorldJamVM
qemu-ubuntu-arm-cortex-a8-running-jamvm-embedded-jvm.jpg

QEMU with Ubuntu ARM Cortex A8 running JamVM embedded JVM

Ubuntu ARM on QEMU Processor Emulator

There are times when you need to try things on virtualized environment before hand e.g. 1) checking application functionality or 2) actual device shipment is still on its long way. Those were also my cases with ARM Linux. Unlike virtualization in production environment however, putting software to emulate CPU architecture will slow down the guest machine a lot.

Ready-to-use image for from the old Ubuntu 9.10 Karmic is avalaible as suggested in RootStock Wiki .

To run Ubuntu 10,04 Lucid you can create similar .img filled by RootStock generated root file system as described in this post generating lucid-arm.img. Boot image is obtained from Lucid port page, of which I saved with the name vmlinuz-lucid-current-ports which is actually linux kernel 2.6.32-21. Running QEMU is then:

qemu-system-arm -M versatilepb -cpu cortex-a8 \
  -kernel vmlinuz-lucid-current-ports \
  -hda lucid-arm.img -m 256 -append "root=/dev/sda mem=256M devtmpfs.mount=0 rw"

However, adding -redir tcp:3232::22 isn’t directly working (although telnet is showing both directions are functional). This redirection is working with the Karmic image which gives instant ssh on my host laptop as in:

ssh localhost -oPort=3232 -l ubuntu

Note: successful QEMU machine image probably won’t boot successfully with the real board. I can’t use kernel 2.6.38-10 for Lucid rootfs on QEMU, but successfully boot that on DevKit8500D board.

qemu-ubuntu-10.04-lucid-kernel-2.6.32-21.jpg

QEMU console of Ubuntu 10.04 VM

Running Ubuntu on DevKit8500D (Natty Kernel and Lucid RootFS)

BeagleBoard xM that comes with Texas Instruments’ DM3730 DaVinci™ processor has its Chinese sister from Embest, the DevKit8500D evaluation kit. This similarity and eLinux wiki (showing working previous DevKit8000) have made me confident that Ubuntu would also port to this board with no hassle. As always, that wasn’t the story. I tried preinstalled images available on Ubuntu CD Image and final combination that worked out of a series of trial-and-error was Natty kernel with Lucid rootfs.

DevKit8500D TI OMAP3

I bricked one of these DevKit8500D by overvoltaged it to 12V DC. Yes, It has no regulator.

Various howto made net-boot or preinstalled images seem feasible, but trying them is another thing. The first attempt was to boot Ubuntu Lucid 10.04 LTS to have similar distribution as my laptop, but it would stop at boot with the message

Error: unrecognized/unsupported machine ID (r1 = 0x00000ae9).

The above ID (2793 in decimal) isn’t found in Lucid released with linux 2.6.32-21. Ubuntu Natty 11.04 boot image didn’t complain because the ID already listed in /usr/src/linux-source-2.6.38/arch/arm/tools/mach-types

...
 nemini                  MACH_NEMINI             NEMINI                  2793
...

However, ubuntu-11.04-preinstalled-headless-armel+omap.img.gz wouldn’t finish loading the linux kernel 2.6.38 somehow. Hence, I replaced the root file system using rootfs created using RootStock method. After successful boot, I installed linux-image-2.6.38-8-omap_2.6.38-8.42_armel.deb to have the rootfs kernel lib files updated (this would require wireless-crda dependency to be installed).


Creating Lucid RootStock & Replacing Natty’s

Using RootStock relies much on the host environment, in my case (version 0.1.99.3) the laptop has Lucid with 2.6.38 kernel (Natty), and it failed to create rootfs with option --dist natty by stopping at this QEMU error:

qemu: fatal: cp15 insn ee1d6f70
 
R00=4009f960 R01=420822e8 R02=0d696914 R03=000086a8
R04=00008ef0 R05=00000000 R06=000097c9 R07=42082308
R08=00020040 R09=00000000 R10=4009f000 R11=00000000
R12=00008b88 R13=4007f7f8 R14=4008f450 R15=4008aea0
PSR=20000030 --C- T usr32

DevKit8500D also freezed on boot when too many seeds used in the rootfs. A minimal seeds of Lucid rootfs used is

[ubuntu-laptop]$ sudo rootstock --fqdn omap --login ubuntu --password temppwd --imagesize 2G --seed wget,nano,linux-firmware,wireless-tools,usbutils --dist lucid --serial ttyO2 --components "main universe multiverse"

It will retrieve many packages from http://ports.ubuntu.com which takes long and produces i.e. armel-rootfs-201110261541.tgz.

A card at /dev/sdb with Natty boot images are obtained by

gunzip -c ubuntu-11.10-preinstalled-server-armel+omap.img.gz | sudo dd bs=4M of=/dev/sdb

The root file system will reside at /dev/sdb2 while boot images are in /dev/sdb1. To replace this with Lucid rootfs, run following steps

1
2
3
4
5
6
dd if=/dev/zero of=lucid-arm.img bs=1MB count=0 seek=1024
sudo mkfs.ext3 -F lucid-arm.img
sudo mount -o loop lucid-arm.img /mnt
sudo tar -C /mnt -zxf armel-rootfs-<some rootstock generated date>.tgz
sudo umount /mnt
sudo dd if=lucid-arm.img of=/dev/sdb2 bs=1MB count=0 seek=1024

There are reasons for why-not-using the included Ångström Linux (forked to linux-2.6.32-devkit8500) but this method of booting Ubuntu wasn’t straightforward after all. The on-board LAN (using Davicom DM9000AEP chip) doesn’t work and I need to use USB ethernet detected as Davicom DM9601 (a bit ridiculous?). Easycap USB video capture also works with this kernel as it has been part of 2.6.38 drivers/staging compilation.

DM9601 USB-LAN-Card

DM9601 USB LAN

Before coming up with this combo, I’ve tried:

  1. Ubuntu Lucid 10.04 CD Image: ubuntu-10.04-server-armel+omap.img
  2. Ubuntu Oneiric 11.10 CD Image: ubuntu-11.10-preinstalled-server-armel+omap.img.gz
  3. Robert C. Nelson’ Oneiric: ubuntu-11.10-r0-minimal-armel.tar.xz (as pointed out by the above eLinux page which has changed quite regularly since October 2011)

But nothing seemed to work.

Write Your Own MIB File (Tabular)

tags:

When it comes to writing our own MIB, a practical choice might be to write the whole objects as of scalar type (RFC-1212). That means, let’s say we have 2 battery statuses, each of them must be explicitly written individually within the MIB file. Example of calling their voltages:

$ snmpwalk -m +REKTRONIK-MIB -v 1 -c public monitored-host .1.3.6.1.4.1.38610
...
REKTRONIK-MIB::battery1Voltage.0 = INTEGER: 9
REKTRONIK-MIB::battery2Voltage.0 = INTEGER: 11
...

If additional 3rd battery is to be monitored, REKTRONIK-MIB.txt in this example must be modified. In small scale we don’t need consistent MIB as changes are manageable, but if a whole bunch of different people must reference to this, a better way is to have tabular object where the above batteries are indexed instead of ended with “.0” scalar identifier.

Quick approach by checking established LM-SENSORS-MIB.txt shows at least we need three object definitions inside the MIB file:

snmp-mib-tabular-object-basics.jpg

Components of writing tabular MIB

Its stemmed MIB tree to show the (1) Table, (2) Entry, and (3) Index:

...
            |     |  |     +--lmFanSensorsTable(3)
            |     |  |     |  |
            |     |  |     |  +--lmFanSensorsEntry(1)
            |     |  |     |     |  Index: lmFanSensorsIndex
            |     |  |     |     |
            |     |  |     |     +-- -R-- Integer32 lmFanSensorsIndex(1)
            |     |  |     |     |        Range: 0..65535
...

Now the writing part of those three types to our MIB, plus the batteryVoltage which is the actual object to be indexed in the final SNMP monitoring.

75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
batteryTable OBJECT-TYPE
    SYNTAX     SEQUENCE OF BatteryEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "The (conceptual) table of batteries contained by the
        module."
    ::= { monitor 1 }
 
batteryEntry OBJECT-TYPE
    SYNTAX     BatteryEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "A (conceptual) entry for one battery contained by
        the module.  The batteryIndex in the index represents
        the entry in the batteryTable that corresponds to the
        batteryEntry.
 
        As an example of how objects in this table are named,
        an instance of the batteryVoltage object might be
        named batteryVoltage.3"
    INDEX { batteryIndex }
    ::= { batteryTable 1 }
 
batteryIndex OBJECT-TYPE
    SYNTAX      DeviceIndex
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
            "A unique value, greater than zero, for each battery. 
            It is recommended that values are assigned contiguously
            starting from 1."
    ::= { batteryEntry 1 }
 
batteryVoltage    OBJECT-TYPE 
   SYNTAX Integer32 
   ACCESS read-only 
   STATUS current 
   DESCRIPTION 
      "Voltage A/D value" 
   ::= { batteryEntry 2 }

There are some header parts of course, check the resulting REKTRONIK-MIB.txt here.

The tree view becomes:

            +--private(4)
            |  |
            |  +--enterprises(1)
            |     |
            |     +--rektronik(39559)
...
            |        |
            |        +--monitor(2)
            |        |  |
            |        |  +--batteryTable(1)
            |        |  |  |
            |        |  |  +--batteryEntry(1)
            |        |  |     |  Index: batteryIndex
            |        |  |     |
            |        |  |     +-- -R-- Integer32 batteryIndex(1)
            |        |  |     |        Textual Convention: DeviceIndex
            |        |  |     |        Range: 1..2147483647
            |        |  |     +-- -R-- Integer32 batteryVoltage(2)
            |        |  |     +-- -R-- Integer32 batteryCurrent(3)
            |        |  |
            |        |  +--environment(2)
            |        |  |  |
            |        |  |  +-- -R-- Integer32 temperature(1)
            |        |  |  +-- -R-- Integer32 humidity(2)
...

and example of getting SNMP is

$ snmpwalk -m +REKTRONIK-MIB -v 1 -c public monitored-host .1.3.6.1.4.1.38610
REKTRONIK-MIB::name.0 = STRING: "RekMini"
REKTRONIK-MIB::version.0 = STRING: "1.0"
REKTRONIK-MIB::date.0 = STRING: "2011-09-08"
REKTRONIK-MIB::batteryIndex.22 = INTEGER: 22
REKTRONIK-MIB::batteryIndex.23 = INTEGER: 23
REKTRONIK-MIB::batteryVoltage.22 = INTEGER: 9
REKTRONIK-MIB::batteryVoltage.23 = INTEGER: 11
REKTRONIK-MIB::batteryCurrent.22 = INTEGER: 2
REKTRONIK-MIB::batteryCurrent.23 = INTEGER: 2
...

in the above example any additional 3rd battery voltage insertion will be OID “REKTRONIK-MIB::batteryVoltage.24

Running Raddle (2): snmpd & Replay Custom Private Enterprise MIB

Net-SNMP wiki gives tutorial on extending snmpd using Perl. In basic run of Raddle (previous post) this involves r1.pl called by r1.conf fed to snmpd. Private enterprise MIB i.e. Microchip’s in this example can be replayed without really ever captured the real device’s SNMP data. This is necessary when the actual device is yet existed; normal situation when developing.  There are two simple ways of replaying this artificial SNMP data over which either way requires correct OID.

First put the Microchip.TXT (the MIB file) under /usr/share/snmp/mibs to easily exchange OID canonical form and name vice versa while making dummy. In this case I’ve modify the MIB to have some additional object i.e. name:
$ snmptranslate -m +Microchip -On Microchip::name
.1.3.6.1.4.1.17095.1.1

so we can then use this correct OID for our dummy.

How?

  1. use SetMIBValue() in r1.pl
    $agent->SetMIBValue( '.1.3.6.1.4.1.17095.1.1', ASN_OCTET_STR, "Microchip");
    $agent->SetMIBValue( '.1.3.6.1.4.1.17095.3.13', ASN_INTEGER, 82);
  2. Feed r1.snmp for playing as in
    $agent->ParseDataFile( '/usr/local/etc/snmp-emulator/r1.snmp', 0 )

    with the content of

    .1.3.6.1.4.1.17095.1.1 = STRING: Microchip
    .1.3.6.1.4.1.17095.3.13 = INTEGER: 82

In all above two examples we can only GET for Raddle to return an answer for each OID. GETNEXT as in bulk snmpwalk won’t give output because they are not sequenced.

A sample of sequenced data inside a real snmpwalk dump is:

$ snmpwalk -v 1 -c public -On localhost
 
.1.3.6.1.2.1.1.1.0 = STRING: Linux xp-racy 2.6.38-10-generic #46~lucid1-Ubuntu SMP Wed Jul 6 18:40:11 UTC 2011 i686
.1.3.6.1.2.1.1.2.0 = OID: .1.3.6.1.4.1.8072.3.2.10
.1.3.6.1.2.1.1.3.0 = Timeticks: (496371) 1:22:43.71
.1.3.6.1.2.1.1.4.0 = STRING: Root  (configure /etc/snmp/snmpd.local.conf)
.1.3.6.1.2.1.1.5.0 = STRING:
.1.3.6.1.2.1.1.6.0 = STRING: Unknown (configure /etc/snmp/snmpd.local.conf)
.1.3.6.1.2.1.1.8.0 = Timeticks: (0) 0:00:00.00
.1.3.6.1.2.1.1.9.1.2.1 = OID: .1.3.6.1.6.3.10.3.1.1
.1.3.6.1.2.1.1.9.1.2.2 = OID: .1.3.6.1.6.3.11.3.1.1

thus, we can only

$ snmpget -m +Microchip -v 1 -c public localhost Microchip::control.13
Microchip::control.13 = INTEGER: 82

or from other system with no Microchip MIB use

$ snmpget -v 1 -c public 192.168.40.105 .1.3.6.1.4.1.17095.3.13
SNMPv2-SMI::enterprises.17095.3.13 = INTEGER: 82

The tree below may visually explains sequenced data for GETNEXT where our Microchip is branched at private.enterprises.microchip :

$ snmptranslate -m +Microchip -Tp
 
+--iso(1)
   |
   +--org(3)
      |
      +--dod(6)
         |
         +--internet(1)
            |
            +--directory(1)
            |
            +--mgmt(2)
            |  |
            |  +--mib-2(1)
            |     |
            |     +--system(1)
            |     |  |
...
            +--private(4)
            |  |
...
            |  +--enterprises(1)
            |     |
...
            |     +--microchip(17095)
            |        |
            |        +--product(1)
            |        |  |

How GET and GETNEXT appeared in SNMP can be viewed by running snmpd in debug mode with this options:

$ snmpd -m +Microchip -f -L -V -C -I vacm_vars -c /usr/local/etc/snmp-emulator/r1.conf
NET-SNMP version 5.3.1
Connection from UDP: [127.0.0.1]:32770
Received SNMP packet(s) from UDP: [127.0.0.1]:32770
  GET message
    -- control.13
← Before After →