glogglog

神秘的ARP包

(09:22:25 PM) smellydog: 一台机器以前两个网卡分别是eth0[00:03:0d:c0:1f:25][192.168.1.9]和eth1[00:10:13:50:a3:43][没有绑定IP],其中001013的是一个USB网卡,为了提高性能,我想把[192.168.1.9]绑定到那个USB网卡上,于是我修改了/etc/udev/rules.d/70-persistent-net.rules把两个的名字对调了一下,现在是 eth0[00:10:13:50:a3:43][192.168.1.9]和eth1[00:03:0d:c0:1f:25][没有绑定IP],问题来了,我发现网络上一直有00:03:0d:c0:1f:25发出来的Gratuitous ARP包号称它是192.168.1.9,而eth0[00:10:13:50:a3:43]当然也在回应ARP请求包,这样就冲突了
(09:23:36 PM) juhovh: 我发现网络上一直有00:03:?
(09:23:56 PM) smellydog: 恩wireshark抓得到的
(09:24:39 PM) smellydog: 问题来了,我发现网络上一直有00:03:0d:c0:1f:25发出来的Gratuitous ARP包号称它是192.168.1.9,而eth0[00:10:13:50:a3:43]当然也在回应ARP请求包,这样就冲突了
(09:25:23 PM) PockeyLam left the room (quit: Ping timeout: 246 seconds).
(09:26:43 PM) smellydog: 但是eth1[00:03:0d:c0:1f:25][没有绑定IP]不应该发ARP包吧?我都没有配置它的IP地址,并且还连接在另一个交换机上面
(09:29:09 PM) juhovh: 嗯,不应该发ARP包
(09:29:49 PM) juhovh: 如果它没有IP地址它就不应该发ARP包
(09:30:19 PM) juhovh: 你可以看看路由表
(09:33:59 PM) smellydog: 路由表里面就三项,192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.9
(09:33:59 PM) smellydog: 169.254.0.0/16 dev eth0 scope link metric 1000
(09:33:59 PM) smellydog: default via 192.168.1.1 dev eth0
(09:35:54 PM) juhovh: 那都是eth0,应该没问题,不知道为什么169.254.0.0/16也在那里
(09:37:55 PM) juhovh: 但是如果eth1真的没有IP地址我也不明白为什么要发ARP包
(09:41:32 PM) PockeyLam [~pockey@058177214103.ctinets.com] entered the room.
(09:49:50 PM) smellydog: 对不起好像找到原因了,我用的那个TP-Link路由器有个“静态ARP绑定设置”,因为之前做过[00:03:0d:c0:1f:25]和[192.168.1.9]的绑定,所以我怀疑是路由器不停在冒充[00:03:0d:c0:1f:25]发Gratuitous ARP包宣称[00:03:0d:c0:1f:25]是[192.168.1.9]。一个证据是我刚才把[00:03:0d:c0:1f:25]的网线拔了,还是能抓到00:03:0d:c0:1f:25发出来的Gratuitous ARP包号称它是192.168.1.9,现在我在路由器里面取消了绑定,问题就解决了



Tags: arp | networking | linux |

Got Motorola E6 camera works in skype

What?

I made a uvcvideo patch to make Motorola E6 camera works in skype in 320x240 mode.

Why?

I have a Motorola E6 cellphone, which has a 2.0M pixel camera. If you set USB mode as "Webcamera", after connecting to PC, this cellphone can act as a webcamera. It works fine in 640x480 mode, but in lower resolutions like 320x240, the video overlaps. The problem is skype, which I used for video chatting with my gf, only send 320x240 resolution. So I cannot use cellphone as webcamera and have to carry an extra webcamera during every trip.

Somebody suggested that a hack to skype config.xml will make skype call with high resolution, but it seems only works in Windows, at least not worked in my Ubuntu9.04 Skype 2.1.0.47.

Indeed, Moto E6 camera(22b8:6006) is a USB video class device. The uvcvideo is in charge to drive this device. But because some issues, when uvcvideo changed the resolution to lower, the hardware didn't change, it send a whole 640x480 frame even when the driver expects a lower resolution

If Skype set resolution to 320x240, the driver malloc a shorter buffer, the length of which is 1/4 of the 640x480 buffer length. When hardware send data to driver, the driver keep complaining "Frame complete (overflow).", that's because the driver buffer is full but hardware keep sending the later 3/4 (640x480)frame. The video is overlapped that's because the driver treat the upper 1/4 of (640x480) frame data as one 320x240 frame data, the first row of 640x480 frame converted to the first and the second row in 320x240 frame. The left part converted to the first row, the right part converted to the second row. So the result is the left part and the right part of the upper 1/4 of (640x480) video, overlaped in 320x240 video, the lower 3/4 video just gone. Here is the snapshot of the videos.

From uvc

And this script verified my guess.

How?

But it seems no solution for this problem. Windows driver maybe works fine, but I have no Windows system at hand. And this thread gave me an idea. It's pretty simple: it store the (640x480) frame data to somewhere and convert them to (320x240) frame data when the last piece of package arrived.

At first, I treat the frame data as bitmap, two bytes is a pixel, and compress it to 1/4. The result looks ugly.

From uvc

Then I found the frame data is in YUYV format, in which 2 pixels will be defined in each macropixel (four bytes). I realized that my previous method make video lost some components. The second solution is: only keep the even(th) rows pixels of the original frame, in each row only keep the 2*even(th) cols pixels. That's is, in one row, copy 2 pixel(4byte), and skip 2 pixel(4byte), copy 2 pixel, skip 2 pixel....etc. This method have an advantage of avoiding compute YUV components of each pixel, disadvantage is obvious: heavy sawtooth

From uvc

So the anti-aliasing is needed, the final solution is to compute the nearby 4 pixel to get the result 1 pixel.

From uvc

Usage

1. Get the source from uvcvideo(install mercurial if needed):

 

hg clone http://linuxtv.org/hg/~pinchartl/uvcvideo/

 

2. Download this patch file to uvcvideo directory and apply the patch. (Warning this path is based on 12393:756ad91a832e)

cd uvcvideo && wget http://sevenever.googlecode.com/svn/trunk/misc/patch_MOTO_E6_to320.patch && patch < patch_MOTO_E6_to320.patch 

3. Make

make

4. Test

 

sudo rmmod uvcvideo ;sudo rmmod videodev;sudo rmmod v4l1_compat 

sudo insmod v4l1-compat.ko; sudo insmod videodev.ko; sudo insmod uvcvideo.ko to320=1

I have add a module parameter "to320" to uvcvideo.ko, if this parameter is 0, the patch will not work. Command to change this parameter is "echo 1 | sudo tee /sys/module/uvcvideo/parameters/to320".

now plugin cellphone and launch skype.

5. if everything is OK, you can install this module.

mv v4l/v4l1-compat.ko /lib/modules/`uname -r`/kernel/drivers/media/video/.

mv v4l/videodev.ko /lib/modules/`uname -r`/kernel/drivers/media/video/.

mv v4l/uvcvideo.ko /lib/modules/`uname -r`/kernel/drivers/media/video/uvc/.

run modconf to reload uvcvideo and append parameter "to320=1"

Better solution

If this camera works fine in Windows, probably there some issues about the uvc driver. Later after I come back to Shanghai, a USB traffic dump is scheduled. If I can confirm that hardware has no problem, this dirty hack is not needed.

End

Thank you for reading up this post and be patient to my poor English, here is my little gift:

From uvc



Tags: uvcvideo | E6 | camera | linux |

duplicate symbol in dynamic library

(21时29分58秒) smellydog: Hi, I have a liba.so which has function libfuncA(), and libb.so which has function libfuncB(), libfuncB calls libfuncA(). In my main.c, I define another libfuncA(), it calls libfuncB(). All this is compiled smoothly, but when run, I got segment fault, what's wrong?

(21时31分24秒) smellydog: All commands to compile is below:
(21时31分24秒) smellydog: gcc --share -o liba.so liba.c
(21时31分24秒) smellydog: gcc --share -o libb.so libb.c
(21时31分24秒) smellydog: gcc -c -o test.o test.c
(21时31分24秒) smellydog: gcc -o test test.o -L. -lb
(21时32分18秒) smellydog: I'll give you source if you need. Thanks!
(21时33分20秒) davidr_: smellydog: have you localised where the segfault is? e.g. compile all your objects with -g and run via gdb?
(21时38分14秒) smellydog: davidr: It seems be the program call the libfuncA() defined in main.c instead of libfuncA() in liba.so, which make a infinite recursion.
(21时40分49秒) smellydog: I solved the segment fault by renaming libfuncA() in main.c to funcA(), as long as different from function name in liba.so.
(21时43分21秒) smellydog: But I don't know how to avoid such problem, because I link my program to some libxxx.so, I don't know whether libxxx.so refering some function with the same func name as my function in other library.
(21时44分32秒) davidr_: smellydog: ok; so the way symbol resolution in shared objects works by default is as follows: if the symbol is defined in the main executable; then then symbol takes prescidence
(21时45分28秒) davidr_: smellydog: you need to mark libfuncA() with __attribute__ ((visi-bility ("hidden")))

(21时45分44秒) davidr_: (drop that hypen in visibility; was a typo)

(22时18分06秒) smellydog: davidr_: I followed your instruction, add __attribute__ ((visibility ("hidden"))) to libfuncA() in test.c, but I got some error:"hidden symbol `libfuncA' in test.o is referenced by DSO" while linking.
(22时23分39秒) davidr_: smellydog: so I think you might have another problem - how as libbfunc() expecting to load liba? are you doing a dlopen() on it?
(22时26分10秒) smellydog: davidr_: I didnot call dlopen(), just include <liba.h> and compile it with -lb
(22时26分47秒) davidr_: smellydog: ok, so the problem you have is how does libb know to open liba? they have no defined relation ship at the moment
(22时27分01秒) smellydog: davidr_: sorry, the compile command line is :gcc --share -o libb.so libb.c
(22时27分20秒) davidr_: smellydog: sure, but there's no mention of liba there
(22时28分00秒) davidr_: so you have test.exe, which is explicityly linked to libb.so. but when you run text.exe, it doesn't know to load liba
(22时28分26秒) davidr_: if you run ldd <test> you'll see which libraries are linked in at compile time
(22时28分42秒) davidr_: to get access to any other libraries, you'll have to explicitiy load them at runtime
(22时28分59秒) smellydog: but I did not get test.exe, got error while link.
(22时30分26秒) davidr_: smellydog: sure, if you revert the visibility change you'll see what I mean. I didn't understand your full problem at the beginning, the visibility thing isn't the (full) solution
(22时33分50秒) smellydog: davidr_:yes, after revert the visibility change and link, I get test.exe, which links to libb.so, no liba.so

(22时40分20秒) smellydog: davidr_: how to aviod such problem? Do I must know every symbol the library used?
(22时40分44秒) davidr_: smellydog: ok you've got a couple of options; but you should probably go and read up on shared libraries
(22时41分05秒) davidr_: smellydog: why have liba and libb in seperate libraries for a start?

(22时49分34秒) smellydog: davidr_: It's just an example, Actually this problem is from my working, I write a program main.c which defined a connect() function, and I compile main.c and link it to Oracle oci library libclntsh.so.10 with -lclntsh. But I got segment fault while running, after debug, I found it is caused by a infinite recursion. I guess the connect() in main.c is called from other lib. So I do this test.

(22时50分53秒) noshadow: smellydog: connect is a standard library functions. of course things might segfault if you replace it with a function with other call semantics....
(22时51分19秒) davidr_: smellydog: ok. So in terms of what you are doing (in the test program); you need to explicity load liba from libb; so in libbfunc() have something like:- {handle = dlopen("liba); myfunc = dlsym(handle, libafunc); myfunc() }
(22时57分10秒) smellydog: davidr_: Thanks! Now I know connect() is a standard library functions, and I should not "rewrite" it ever, but what about other standard library functions I don't know and "rewrite" them by mistake. can gcc give me some waring? such problem is hard to debug.

(23时00分31秒) noshadow: smellydog: only way I see it could warn is when the appropiate header is installed. Then it will usually warn as the function will have different prototypes. But all the headers are quite big.
(23时01分04秒) noshadow: A way to avoid such problems is to make all functions static you do not need outside the file.
(23时02分02秒) noshadow: And to check names you use between files (under linux installing development manpages and looking there) or using names unlikely to be default (like modulename_function)...
(23时04分22秒) smellydog: noshadow: Thanks for reply! Is there some tools to check names between files?

(23时06分52秒) noshadow: smellydog: perhaps splint or co might do so..
(23时09分19秒) smellydog: noshadow: Thanks! I'm go for them. I learn much about shared library and its loading, and can you suggest some readings about it?

 


Test codes:

-----------------------------------------------------------

/*liba.h:*/

int libfuncA();

-----------------------------------------------------------

/*liba.c*/

#include <stdio.h>

int libfuncA()
{
    printf("from lib A\n");
    return 0;
}

-----------------------------------------------------------

/*libb.h*/

int libfuncB();

-----------------------------------------------------------

/*libb.c*/

#include <stdio.h>
#include "liba.h"

int libfuncB()
{
    printf("from lib B\n");
    libfuncA();
    return 0;
}

-----------------------------------------------------------

/*test.c*/

#include <stdio.h>
#include "libb.h"

int libfuncA(){
    printf("from funcA in main\n");
    libfuncB();
}
int main()
{
    libfuncA();
    return 0;
}


-----------------------------------------------------------

My solutions is:

-----------------------------------------------------------

in test.c


- int libfuncA(){
+ static int libfuncA(){

-----------------------------------------------------------

compile:
gcc --share -o liba.so liba.c
gcc --share -o libb.so -L. -la libb.c
gcc -c -o test.o test.c
gcc -o test test.o -L. -lb

-----------------------------------------------------------

 

 



Tags: gcc | linux |
sevenever@gmail.com
Copyright © 2008. All rights reserved.