Pátek IX 12, 2008

DTrace: Insufficient registers to generate code

Recently during a development of a DTrace script I hit a strange dtrace error. The intent was to trace TCP packets flow at different levels in IP stack, dumping sequence and acknowledge numbers. It started as a small script and I continued adding more and more lines until next attempt to run the script failed with a strange error message I have never seen before. The error message was:

dtrace: failed to compile script ./tcp.d: Insufficient registers to generate code

I didn't want to spend much time as I suspected I did some common mistake, which was already hit by many people before. Unfortunately not. According to google search engine, it's not a common mistake and it wasn't hit by many people before. It motivated me to post a blog to make life easier for the next one. First I thought that my script exceeded number of allowed self variables, but commenting out assignments to new self variables had no effect. I've started to go backwards by removing last changes from the script, until I got back to the point where the script compiled fine. It showed that the line, which caused the compilation problem contained quite complex expression, which used several memory dereferences. The aim of faulty macro was to read memory, not necessarily aligned, in network byte order. Reading 16 bits was fine, while reading 32 bits by reassembling the value from 4 bytes broke the compilation. The workaround was to split memory operation to several statements (macro READ_DWORD), rather than having all memory dereferences in one expression (macro DWORD). The examples follows. They do no real work, only demonstrate.

Broken example:

#define WORD(_x_) (((uint8_t \*)(_x_))[0] \* 256 + ((uint8_t \*)(_x_))[1])
#define DWORD(_x_) WORD(_x_) \* 65536 + WORD((uint8_t \*)(_x_) + 2)

         x = &`utsname;
         result = DWORD(x);

# dtrace -C -s /tmp/broken.d 
dtrace: failed to compile script /tmp/broken.d: Insufficient registers to generate code

Version which compiles:

#define WORD(_x_) (((uint8_t \*)(_x_))[0] \* 256 + ((uint8_t \*)(_x_))[1])
#define READ_DWORD(_x_, _dest_) _dest_ = WORD(_x_) << 16; \\
     _dest_ += WORD((uint8_t \*)(_x_) + 2);

         x = &`utsname;
         READ_DWORD(x, result);

# dtrace -C -s /tmp/good.d   
dtrace: script '/tmp/good.d' matched 1 probe
CPU     ID                    FUNCTION:NAME
  0      1                           :BEGIN  1400204879

Čtvrtek VIII 30, 2007

U:fon runs OpenSolaris

This entry is not about close encounters of third kind, what one can think after reading the title, this entry is about a new mobile internet provider in Czech Republic called U:fon. His offer includes two internet (CDMA) connection options with theoretical download maximum of 153kb/s and 3.1Mb/s. Yesterday and today I had a chance to try the first option. The package from ISP included a phone with integrated USB modem (see below). Note that the faster option includes small modem integrated into USB stick, but it's more expensive.


After connecting the modem it showed up as AXESSTEL CO., LTD. DATA MODEM. Unfortunately the modem likely doesn't conform to USB ACM/CDC specification and class driver doesn't attach. Anyway it didn't stop me from exploring it. It was a question of few attempts to identify bulk data in/out endpoints used by modem to communicate with the host. While playing with the modem via ugen driver, it surprised me that it doesn't support such basic command like "ATI". Well, I don't mind if dialing works. The PPP configuration for U:fon was almost same as I did in the past for mobile internet from O2. The difference was username/password which is simply ufon/ufon. Unlike one of the sources on the internet, which described manual DNS configuration, I found that the PPP server provides DNS records, so I took advantage of pppd's usepeerdns option.

Beta driver package for OpenSolaris

I added basic support for AXESSTEL modem to my package, which is provided as is. If you are U:fon subscriber and want try the connection from OpenSolaris distribution, you can download the package and follow the instructions from my previous CDMA entry. I haven't done any serious speed test. My download speed was somewhere between 1-100 kb/s, due to variable signal quality. The best ping I achieved was around 350 miliseconds.

Pátek V 18, 2007

Two "secrets" of cdrw

When I first tried burning using cdrw(1) on Solaris I started to like it's simple command line syntax. While using this tools I found two things not described in its man page:

cdrw command can print media type

The cdrw command has undocumented debugging flag -V. Once I encountered a blank media and it was not obvious if it's a CD or DVD, there was no indication of media type on it. I searched how to find the information simply by software. I found nothing, however, later when I was looking at the cdrw code, I found that this tool actually reads the media type, but prints it only with debug turned on. See get_media_type() in usr/src/cmd/cdrw/device.c source file. When I discovered this, it was already too late. But next time I could use:

cdrw -M -V

Which would print among other things something like: "CD-ROM found" or DVD-RAM, DVD+R, DVD-R, etc.

set/get the read speed of CD/DVD drive

Sometimes I want listen to music or watch a film on Solaris from the CD/DVD media. However, the drive is spinning the media at full speed and this is quite noise. Especially, when I listen music the drive constantly switches between noise and silence according to how the player buffers data. Yes, the best workaround is not to run playback from CD/DVD. The other option is to limit the spinning speed by software. I found some usefull code again in cdrw. The cdrw command allows you to specify writing speed using -p option. Hmm, it still didn't help, I want to set reading speed. Reading the source code of cdrw, one can find that the function used to control write speed can also control the read speed, but currently no command line option allows this. I've helped myself with mdb(1) debugger, writing short script, which calls a particular function with arguments saying that I want to control the read speed of the drive. It's really not clean solution, but workaround. It works for me about two years. You may download the script cdspeed. The syntax is:

Usage: cdspeed [speed]

If invoked without speed argument, it gets the read speed, otherwise it attempts to set the read speed to given value. Before running the command, make sure that there is a media in the drive. Also I doubt that script works on drives, which are not burners - I cannot try as I don't have one. The script supports x86 platforms only. But if it after all still works for you, you can enjoy listening or watching from CD/DVD!

Čtvrtek II 22, 2007

Internet over CDMA for the best operating system

To make an internet connection on Solaris laptop easy, I've prepared a support package. It is provided "as is". Use at your own risk. If you want to accept and continue, you will need:

  • valid contract to be able to use internet over CDMA in Czech Republic
  • a x86 computer running Solaris OS, preferably some latest OpenSolaris based distribution like Solaris Express
  • an usb CDMA modem either older GTRAN or AnyDATA
  • package VTBcdmacz.pkg
  • optional experimental package VTBcdmafil.pkg with filtering module, which blocks sending of packets with source ip address other than assigned one. Such an action is usually followed by immediate disconnect by ISP. (requires Solaris Express build > 60).
  • credentials for your connections: user(mobile number) and password, which you will get with the modem

Quick installation:

The procedure is easy, install the package and use /usr/sbin/cdmactl, which is an user interface for setting up the connection and controlling it (it's a simple perl script). Here is an example:

# ### Install the package from the internet or local copy:
# pkgadd -d http://blogs.sun.com/vita78/resource/cdma_052007/VTBcdmacz.pkg

# ### Configure your account, check the system and go online 
# /usr/sbin/cdmactl configure
# /usr/sbin/cdmactl check
# /usr/sbin/cdmactl start

What commands does cdmactl offer?

  • cdmactl configure - setup the configuration, will ask for your credentials and write the configuration files for pppd daemon.
  • cdmactl check - to make sure things are working correctly, correct any defects it will find
  • cdmactl start - connect to the internet, once you have configured your system and ensured it is ready, this command enables the connection to the internet. You can monitor the activity with pgrep -l cdma and tail -f /var/adm/messages.
  • cdmactl stop - disconnect from the internet
  • cdmactl signal - monitor the signal quality. To find a good place where the modem or antenna will have a signal and the connection will work at best, you can try this experimental feature, which is available only for AnyDATA modem.

Pondělí X 09, 2006

Překladový online slovník angličtiny v příkazové řádce, aneb www.slovnik.cz v terminálu

Čas od času, jako člověk pracující s cizím jazykem potřebuju slovník k tomu, abych si přeložil slovíčko, kterému nerozumím, občerstvil nějaký význam cizího slova, atp. Nemám nic proti papírovému slovníku, alespoň kouknu někam jinam než do blikající obrazovky, ale díky své vrozené lenosti je pro mě rychlejší použít elektronický slovník na počítači, když zrovna náhodou u něj sedím. S oblibou jsem používal online překladové slovníky www.slovnik.cz a slovnik.seznam.cz, ale na druhou stranu mi vadily reklamy a klikání, bez kterého se v prohlížeči jen těžko existuje. Naštestí je tady řešení i pro příkazovou řádku, kdy si vystáčím s jediným skriptem, bez lokální databáze slovíček. Autorem myšlenky a první implementace je Petr Nýč (alias jetpac), jehož skript jsem si oblíbil a vylepšil.

Co k provozování online slovníku v terminálu potřebuju?

  • perl - verze 5+
  • lynx - prohlížeč pro příkazovou řádku
  • slovnik.pl - perlovský skript pro přístup k online slovníkům
  • cstocs - pro odstranění diakritiky z výstupu skriptu

Perl, lynx a skript jsou z pochopitelných důvodů nutností a bez nich to fungovat nebude, na druhou stranu utilitka cstocs není povinná, je použita pro odstranění diakritiky z přeložených slovíček, k čemuž se s oblibou uchyluju při svých věčných potyčkách s terminálem a fonty, zvláště pak, když nade mnou vyhrávají.

Jak to funguje? Skript pracuje s oběma výše uvedenými slovníky najednou, pokud není v konfiguračním souboru uvedeno jinak, vyhledá překládané slovo v obou systémech a výsledky spojí dohromady. Dále je v konfiguraci možné povolit, nebo zakázat používaní diakritiky, HTTP proxy, která slouží k přístupu k webu, PAGER, což je program k prohlížení výsledků, není-li zadán, výsledky jsou vypsány na standardní výstup. Konfigurace se načítá ze souborů /etc/slovnikrc a $HOME/.slovnikrc, a tady je příklad toho, jak může konfigurační soubor vypadat:

# Seznam serveru, ze kterych se ctou slovicka

# nastaveni diakritiky ve vystupu, 0 - ne, 1 - ano

# jmeno programu, ktery se ma pouzit pro prohlizeni vysledku vyhledavani

# nastaveni HTTP proxy serveru pro pristup k internetu

Poznámka nakonec: skript překládá obousměrně tj. z angličtiny i z češtiny zároveň, pokud jej ale přejmenujete / nalinkujete na encz, nebo czen, stává se z něj jednosměrný slovník do češtiny, resp. angličtiny.

Středa VIII 02, 2006

OpenSolaris running on two dual core notebooks

Recently I had an oportunity to test OpenSolaris OS on two dual core notebooks. Namely Sony Vaio VGN-SZ1XP/C and Toshiba Tecra model M5. Both are equipped with Intel® Core™ Duo CPU. The dual core CPU works fine and appears in the OS as there are two independent CPUs. The installation of OpenSolaris OS on both machines was fluent, one limitation for somebody could be, that network card drivers are currently not supported in the installer, so potential network installation will be tricky. Also don't expect that everything e.g. like fingerprint reader or bluetooth will work now. However, the overall impression from both notebooks is good and all core peripherials are working in OpenSolaris.

Here is the summary of things, which were tested:

NotebookSony Vaio VGN-SZ1XP/CToshiba Tecra M5
CPU2 virtual cpus detected in the OS2 virtual cpus detected in the OS
Graphics card 2DOK with Xorg, see note belowOK with Xorg and driver from NVidia
External monitorOK using TwinViewOK using TwinView
Network cardOK using driver from http://www.marvell.com/OK using internal latest e1000g driver
DVD burningOKOK

Note: There are two graphics card in the Vaio notebook: NVidia GeForce GO 7400 and Intel 945GM. The user can switch between them by a physical switch located above the keyboard labeled "stamina/speed" (reboot is needed after the change). NVidia card works with the binary driver from http://www.nvidia.com/ and Intel will be hopefully supported soon by internal Xorg's 810 driver, now one can use VESA driver, which works fine in 2D.

Pondělí III 13, 2006

CZOSUG - Boot Camp

I participated at CZOSUG Boot Camp on Saturday. Generally this action was focused on Solaris/OpenSolaris installation and device drivers. I was trying there to explain that it is very easy task to work in Solaris OS with USB devices, especially modems. Thanks to ugen driver it is nearly only about finding correct endpoints containing input and output streams from/to the modem and connect them to ppp daemon. The presentation's title is CDMA USB modem - using ugen(7D) in Solaris OS. that is me

Středa XII 07, 2005

CZOSUG - ZFS presentation

Today in the evening, we had a chance to learn about our new filesystem - ZFS and it's cool features. The presentation was delivered by Don, Evan and Mark. Obviously this is an interesting topic and it attracted more people than usually. I've counted nearly 40 heads. And here are some pictures: picture1 picture2

Čtvrtek X 20, 2005


Users of x86 32bit machines following the howto use Eurotel Data Expres (CDMA) on Solaris will likely experience an error message from _cat_ after 10 seconds from establishing the connection: \*cat: input error on if1in10: I/O error\* It happens because the ugen_bulk_timeout tunable is not working (on particular platforms). The root cause is that the compiler has optimized a reference to this tunable away. Simply - the timeout value can't be tuned by changing the _/etc/system_ until the bug 6333195 is fixed. Thanks to Mirek for discovering it and thanks to authors of _DTrace_ tool, since it was quite simple to find the root cause by tracing the function flow in the kernel and dumping their arguments. Here is a list of possible workarounds:
  • periodically ping some machine through the sppp0 interface - your modem will not become idle.
  • use an ugly loop in shell: ( while :; do cat if1in10; done ) | pppd call etcdma > if1out11
  • use (at own risk) a small shell/mdb script cdma_ugen_bulk_timeout, which will increase the timeout. It runs the kernel debugger and modifies one instruction's operand (holding the timeout value) in ugen_epx_bulk_req() function. The change is valid until a next reboot and should be done before starting _pppd_ . You should be a superuser to launch it. The correct output looks like:
    noname:/tmp# chmod +x /tmp/cdma_ugen_bulk_timeout
    noname:/tmp# /tmp/cdma_ugen_bulk_timeout
    ugen_epx_bulk_req+0x5a:         0xa             =       0x57e40
TBD: I'd like to use a special launcher, which will restart _I/O_ on timeout. That's what I'm currently working on and hope it will sort out the problems with ugen_bulk_timeout since no change of the tunable will be required.

Pátek IX 09, 2005

Eurotel Data Expres (CDMA) v operačním systému Solaris 10, Solaris Express a Nevada

Pár slov na úvod

Rádi bychom se s Vámi podělili o zkušenosti, které jsme s Petrem Šumberou získali při provozování služby Eurotel Data Expres v operačním systému Solaris verze 10 a vyšší. Eurotel Data Expres je bezdrátové vysokorychlostní připojení k internetu poskytované (jak jinak) společností Eurotel v České Republice. Služba využívá technologii CDMA ve frekvenčním pásmu 450 MHz a je nabízena od srpna 2004. Pro připojení k internetu je dodáván USB modem Gtran GPC-6420, který má podporu v MS Windows, Linuxu a jak vyplyne z následujících řádků, funguje po troše úsilí i v OS Solaris.

Na rozdíl od Linuxu, kde je podpora ve formě kernelového driveru, v Solarisu neexistuje specifický ovladač (ne na úrovni kernelu) pro CDMA modem, který by jej podporoval jako svůj primární cíl. Místo vývoje chybějícího ovladače pro kernel jsme se spokojili s již existujícím obecným ovladačem ugen pro USB zařízení, která nemají svůj kernelový ovladač. Další variantou by bylo využití knihovny libusb, ale komplikuje ji potřeba zdrojového kódu a kompilace - od této varianty bylo upuštěno, je zde zmíněna pouze jako další možná cesta.

Ovladač ugen

Je obecný ovladač USB zařízení, který umožňuje přístup k hardware pomocí standardních unixových operací open/close/read/write/aioread/aiowrite nad soubory. Součástí systému je od verze 10 (port z FreeBSD) a jeho smyslem je zjednodušit psaní ovladačů pro různá USB zařízení a umožnit jejich přesunutí do user-space. S použitím ugen pro CDMA modem vznikají 2 méně závažné problémy:

  • ugen nepodporuje "polling" ani neblokující io operace pro bulk přenosy (viz man ugen(7D))
  • ugen nastavuje timeout pro operaci bulk read, po jehož vypršení vrací volání read chybu EIO. Výchozí hodnota timeoutu je poměrně nízká - 10 sekund.

První bod dokážeme eliminovat pomocnou aplikací, která čte data z CDMA bez použití poll v blokujícím režimu a následně je předává do pppd rourou. V naší implementaci je pro tyto účely použit program cat. Démon pppd pak čte data ze standardního vstupu (z roury) a zapisuje na standardní výstup, který je přesměrován do CDMA modemu. Toto chování pppd, kdy komunikuje přes standardní vstup a výstup a ne přes terminál, je zapnuto volbou notty.

Druhý bod vede k zásahu do konfigurace jádra a zvednutí výchozí hodnoty timeoutu na hodnotu poněkud vyšší, např. 1h.

Postup aneb Mini-HowTo

Krok 1: Připojení ovladače ugen k CDMA modemu

Následujícími přikazy odstraňte a následně připojte ovladač ugen k CDMA modemu. Po aplikaci je nutný restart systému, aby se změny projevily.

# rem_drv ugen
# add_drv -i '"usb5c6,3196.0"' -m '\* 0666 root sys' ugen
# init 6

Pokud si systém během restartu na nic nestěžoval, pak nastal ten správný čas na fyzické připojení modemu k počítači. Výsledkem by mělo být hlášení v logu (nebo výstupu dmesg), oznamující, že zařízení bylo rozpoznáno ovladačem:

Sep  8 22:45:15 noname usba: [ID 912658 kern.info] USB 1.1 device (usb5c6,3196) operating at full speed (USB 1.x) on USB 1.10 root hub: communications@2, ugen2 at bus address 2
Sep  8 22:45:15 noname usba: [ID 349649 kern.info]      Qualcomm, Incorporated  CDMA Technologies MSM
Sep  8 22:45:15 noname genunix: [ID 936769 kern.info] ugen2 is /pci@0,0/pci1025,57@10/communications@2
Sep  8 22:45:15 noname genunix: [ID 408114 kern.info] /pci@0,0/pci1025,57@10/communications@2 (ugen2) online

a v systému by měl vzniknout adresář:


Pro vysvětlení: kód 5c6 je id výrobce, 3196 id produktu a 0 je číslo instance CDMA modemu. Pokud máte (jen) jeden CDMA modem a objevilo se více instancí, pak to znamená, že některé linky jsou neplatné a nebyly automaticky odstraněny. Tuto situaci většinou řeším odpojením zařízení a příkazem devfsadm -C, který provede úklid adresáře /dev a odstraní všechny neplatné linky, viz man devfsadm(1M). Ovšem rád se nechám poučit, pokud to jde jednodušeji a lépe.

V adresáři /dev/usb/5c6.3196/0/ by se mělo objevit několik souborů (endpoints), resp. symbolických linků:

cntrl0        devstat       if0in1stat    if1in10stat   if1out11stat
cntrl0stat    if0in1        if1in10       if1out11

Jejich popis je nad rámec tohoto textu, nicméňe zájemci si mohou prostudovat manuálovou stránku ugen(7D).

Krok 2: Prodloužení ugen_bulk_timeout

Původní hodnota timeoutu je 10 sekund, což znamená že po deseti sekundách bez aktivity dojde k ukončení připojení díky tomu, že operace read ze vstupního zařízení vrací chybu EIO. Oprava (workaround) je jednoduchá a spočívá přidání řádku do /etc/system, nebo nastavení proměnné za běhu pomocí kernel debuggeru (což ale není triviální ani permanentní). Hodnota timeoutu se udává v sekundách a 1 hodina byla zvolena experimentálně.

V Solaris verze 10 je třeba přidat do /etc/system řádek:

set ugen:ugen_bulk_timeout = 3600

V Nevadě (kódóvé označení příští verze) a Solaris Express se kód ugen přesunul do modulu usba (nícméňe funkčnost zůstala zachována). Zde je třeba přidat do /etc/system řádek:

set usba:ugen_bulk_timeout = 3600

Po změně je nutný restart (init 6), aby systém načetl nové nastavení.

Krok 3: Konfigurace pppd

Je podobná jako v jiných systémech s pppd, např. v Linuxu (viz návod na www.root.cz). Na rozdíl od Linuxu se ppp démonovi neříká jakou rychlostí má komunikovat a se kterým terminálem. Tyto dvě volby jsou nahrazeny volbou notty.

V nastavení jde o: nastavení voleb pppd, chat script, skripty pro automatickou konfiguraci DNS a soubor s heslem pro CHAP. Pro zjednodušení je přiložen archív obsahující všechny potřebné soubory. Po rozbalení archívu je nutné zadat telefonní číslo a heslo přidělené Eurotelem do dvou souborů. Následuje krátký komentář k obsahu archívu:

  1. /etc/ppp/peers/etcdma je call script s nastavením voleb pppd, zadejte své tel. číslo,
  2. /etc/ppp/chat-etcdma je chatscript (viz man chat(1M)) pro navázání spojení,
  3. /etc/ppp/chap-secrets obsahuje údaje pro autentizaci, zadejte své tel. číslo a heslo,
  4. /etc/ppp/options - prázdný soubor, pokud pppd nespouští root, musí tento soubor existovat, jinak pppd skončí s chybou,
  5. /etc/ppp/ip-up slouží k automatické konfiguraci DNS po připojení,
  6. /etc/ppp/ip-down slouží pro obnovení původní konfigurace DNS po ukončení spojení.

Ještě malá poznámka na závěr - skripty ip-up a ip-down předpokládají, že name services používají DNS. Tzn., že /etc/nsswitch.conf obsahuje např. tyto řádky:

hosts:      files dns
ipnodes:   files dns

Více viz man nsswitch.conf(4).

Krok 5: Spuštění připojení

Stačí se přepnout do adresáře /dev/usb/5c6.3196/0 a spustit v terminálu příkaz:

cat if1in10 | pppd call etcdma > if1out11

Krok 6: Monitorování a hledání chyb

tail -f /var/adm/messages

Krok 7: Ukončení připojení

pkill pppd


A na konec obrázek jako důkaz :).


  1. AT příkazy modemu GPC-6420
  2. Domovská stránka projektu OpenSolaris
  3. České stránky o CDMA
  4. Návod na připojení v Linuxu na www.root.cz
  5. Archív konfiguračních souborů



« červenec 2016