Lamdoc船长的宝藏:http://blog.csdn.net/lamdoc/article/details/7690230
除了android_net_netutils.cpp 外 还有一个JNI : android_net_ethernet.cpp
1. frameworks/base/ethernet/java/android/net/ethernet/EthernetNative.java 代码会调用这个JNI
- package android.net.ethernet;
- /**
- * Native calls for sending requests to the kernel,
- * {@hide}
- */
- public class EthernetNative {
- public native static String getInterfaceName(int i); //get eth0, sit0
- public native static int getInterfaceCnt(); //
- public native static int initEthernetNative();
- public native static String waitForEvent();
- }
package android.net.ethernet;
/**
* Native calls for sending requests to the kernel,
* {@hide}
*/
public class EthernetNative {
public native static String getInterfaceName(int i); //get eth0, sit0
public native static int getInterfaceCnt(); //
public native static int initEthernetNative();
public native static String waitForEvent();
}
2. JNINativeMethod gEthernetMethods[]:
- static JNINativeMethod gEthernetMethods[] = {
- {"waitForEvent", "()Ljava/lang/String;",
- (void *)android_net_ethernet_waitForEvent},
- {"getInterfaceName", "(I)Ljava/lang/String;",
- (void *)android_net_ethernet_getInterfaceName},
- {"initEthernetNative", "()I",
- (void *)android_net_ethernet_initEthernetNative},
- {"getInterfaceCnt","()I",
- (void *)android_net_ethernet_getInterfaceCnt}
- };
static JNINativeMethod gEthernetMethods[] = {
{"waitForEvent", "()Ljava/lang/String;",
(void *)android_net_ethernet_waitForEvent},
{"getInterfaceName", "(I)Ljava/lang/String;",
(void *)android_net_ethernet_getInterfaceName},
{"initEthernetNative", "()I",
(void *)android_net_ethernet_initEthernetNative},
{"getInterfaceCnt","()I",
(void *)android_net_ethernet_getInterfaceCnt}
};
3. AndroidRuntime 运行时,会注册 这个NativeMethod:
- int register_android_net_ethernet_EthernetManager(JNIEnv* env)
- {
- jclass eth = env->FindClass(ETH_PKG_NAME);
- LOGI("Loading ethernet jni class");
- LOG_FATAL_IF(eth == NULL, "Unable to find class " ETH_PKG_NAME);
- dhcpInfoFieldIds.dhcpInfoClass =
- env->FindClass("android/net/DhcpInfo");
- if (dhcpInfoFieldIds.dhcpInfoClass != NULL) {
- dhcpInfoFieldIds.constructorId =
- env->GetMethodID(dhcpInfoFieldIds.dhcpInfoClass,
- "<init>", "()V");
- dhcpInfoFieldIds.ipaddress =
- env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass,
- "ipAddress", "I");
- dhcpInfoFieldIds.gateway =
- env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass,
- "gateway", "I");
- dhcpInfoFieldIds.netmask =
- env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass,
- "netmask", "I");
- dhcpInfoFieldIds.dns1 =
- env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "dns1", "I");
- dhcpInfoFieldIds.dns2 =
- env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "dns2", "I");
- dhcpInfoFieldIds.serverAddress =
- env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass,
- "serverAddress", "I");
- dhcpInfoFieldIds.leaseDuration =
- env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass,
- "leaseDuration", "I");
- }
- //注册gEthernetMethods[]
- return AndroidRuntime::registerNativeMethods(env,
- ETH_PKG_NAME,
- gEthernetMethods,
- NELEM(gEthernetMethods));
- }<SPAN style="COLOR: #ff0000"><STRONG><SPAN style="FONT-SIZE: 16px">
- </SPAN></STRONG></SPAN>
int register_android_net_ethernet_EthernetManager(JNIEnv* env)
{
jclass eth = env->FindClass(ETH_PKG_NAME);
LOGI("Loading ethernet jni class");
LOG_FATAL_IF(eth == NULL, "Unable to find class " ETH_PKG_NAME);
dhcpInfoFieldIds.dhcpInfoClass =
env->FindClass("android/net/DhcpInfo");
if (dhcpInfoFieldIds.dhcpInfoClass != NULL) {
dhcpInfoFieldIds.constructorId =
env->GetMethodID(dhcpInfoFieldIds.dhcpInfoClass,
"<init>", "()V");
dhcpInfoFieldIds.ipaddress =
env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass,
"ipAddress", "I");
dhcpInfoFieldIds.gateway =
env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass,
"gateway", "I");
dhcpInfoFieldIds.netmask =
env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass,
"netmask", "I");
dhcpInfoFieldIds.dns1 =
env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "dns1", "I");
dhcpInfoFieldIds.dns2 =
env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "dns2", "I");
dhcpInfoFieldIds.serverAddress =
env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass,
"serverAddress", "I");
dhcpInfoFieldIds.leaseDuration =
env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass,
"leaseDuration", "I");
}
//注册gEthernetMethods[]
return AndroidRuntime::registerNativeMethods(env,
ETH_PKG_NAME,
gEthernetMethods,
NELEM(gEthernetMethods));
}
4. waitForEvent():
- static jstring android_net_ethernet_waitForEvent(JNIEnv *env, jobject clazz)
- {
- char *buff;
- struct nlmsghdr *nh;
- struct ifinfomsg *einfo;
- struct iovec iov;
- struct msghdr msg;
- char *result = NULL;
- char rbuf[4096];
- unsigned int left;
- interface_info_t *info;
- int len;
- LOGV("Poll events from ethernet devices");
- /*
- *wait on uevent netlink socket for the ethernet device
- */
- buff = (char *)malloc(NL_POLL_MSG_SZ);
- if (!buff) {
- LOGE("Allocate poll buffer failed");
- goto error;
- }
- iov.iov_base = buff;
- iov.iov_len = NL_POLL_MSG_SZ;
- msg.msg_name = (void *)&addr_msg;
- msg.msg_namelen = sizeof(addr_msg);
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = NULL;
- msg.msg_controllen = 0;
- msg.msg_flags = 0;
- if ((len = recvmsg(nl_socket_poll, &msg, 0)) >= 0) {
- LOGV("recvmsg get data");
- result = rbuf;
- left = 4096;
- rbuf[0] = '\0';
- for (nh = (struct nlmsghdr *) buff; NLMSG_OK (nh, len);
- nh = NLMSG_NEXT (nh, len)) {
- if (nh->nlmsg_type == NLMSG_DONE) {
- LOGE("Did not find useful eth interface information");
- goto error;
- }
- if (nh->nlmsg_type == NLMSG_ERROR) {
- /* Do some error handling. */
- LOGE("Read device name failed");
- goto error;
- }
- LOGV(" event :%d found", nh->nlmsg_type);
- einfo = (struct ifinfomsg *)NLMSG_DATA(nh);
- LOGV("the device flag :%X", einfo->ifi_flags);
- if (nh->nlmsg_type == RTM_DELLINK ||
- nh->nlmsg_type == RTM_NEWLINK ||
- nh->nlmsg_type == RTM_DELADDR ||
- nh->nlmsg_type == RTM_NEWADDR) {
- int type = nh->nlmsg_type;
- if (type == RTM_NEWLINK &&
- (!(einfo->ifi_flags & IFF_LOWER_UP))) {
- type = RTM_DELLINK;
- }
- if ((info = find_info_by_index
- (((struct ifinfomsg*) NLMSG_DATA(nh))->ifi_index)) != NULL)
- snprintf(result,left, "%s:%d:",info->name,type);
- left = left - strlen(result);
- result =(char *)(result+ strlen(result));
- }
- }
- LOGV("Done parsing");
- rbuf[4096 - left] = '\0';
- LOGV("poll state :%s, left:%d", rbuf, left);
- }
- error:
- free(buff);
- return env->NewStringUTF(rbuf);
- }
static jstring android_net_ethernet_waitForEvent(JNIEnv *env, jobject clazz)
{
char *buff;
struct nlmsghdr *nh;
struct ifinfomsg *einfo;
struct iovec iov;
struct msghdr msg;
char *result = NULL;
char rbuf[4096];
unsigned int left;
interface_info_t *info;
int len;
LOGV("Poll events from ethernet devices");
/*
*wait on uevent netlink socket for the ethernet device
*/
buff = (char *)malloc(NL_POLL_MSG_SZ);
if (!buff) {
LOGE("Allocate poll buffer failed");
goto error;
}
iov.iov_base = buff;
iov.iov_len = NL_POLL_MSG_SZ;
msg.msg_name = (void *)&addr_msg;
msg.msg_namelen = sizeof(addr_msg);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
if ((len = recvmsg(nl_socket_poll, &msg, 0)) >= 0) {
LOGV("recvmsg get data");
result = rbuf;
left = 4096;
rbuf[0] = '\0';
for (nh = (struct nlmsghdr *) buff; NLMSG_OK (nh, len);
nh = NLMSG_NEXT (nh, len)) {
if (nh->nlmsg_type == NLMSG_DONE) {
LOGE("Did not find useful eth interface information");
goto error;
}
if (nh->nlmsg_type == NLMSG_ERROR) {
/* Do some error handling. */
LOGE("Read device name failed");
goto error;
}
LOGV(" event :%d found", nh->nlmsg_type);
einfo = (struct ifinfomsg *)NLMSG_DATA(nh);
LOGV("the device flag :%X", einfo->ifi_flags);
if (nh->nlmsg_type == RTM_DELLINK ||
nh->nlmsg_type == RTM_NEWLINK ||
nh->nlmsg_type == RTM_DELADDR ||
nh->nlmsg_type == RTM_NEWADDR) {
int type = nh->nlmsg_type;
if (type == RTM_NEWLINK &&
(!(einfo->ifi_flags & IFF_LOWER_UP))) {
type = RTM_DELLINK;
}
if ((info = find_info_by_index
(((struct ifinfomsg*) NLMSG_DATA(nh))->ifi_index)) != NULL)
snprintf(result,left, "%s:%d:",info->name,type);
left = left - strlen(result);
result =(char *)(result+ strlen(result));
}
}
LOGV("Done parsing");
rbuf[4096 - left] = '\0';
LOGV("poll state :%s, left:%d", rbuf, left);
}
error:
free(buff);
return env->NewStringUTF(rbuf);
}
- <SPAN style="COLOR: #ff0000"><STRONG><SPAN style="FONT-SIZE: 16px">
- 5. initEthernetNative():</SPAN></STRONG></SPAN><PRE class=java name="code"> static jint android_net_ethernet_initEthernetNative(JNIEnv *env,
- jobject clazz)
- {
- int ret = -1;
- LOGI("==>%s",__FUNCTION__);
- memset(&addr_msg, 0, sizeof(sockaddr_nl));
- addr_msg.nl_family = AF_NETLINK;
- memset(&addr_poll, 0, sizeof(sockaddr_nl));
- addr_poll.nl_family = AF_NETLINK;
- addr_poll.nl_pid = 0;//getpid();
- addr_poll.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
- /*
- *Create connection to netlink socket
- */
- nl_socket_msg = socket(AF_NETLINK,SOCK_RAW,NETLINK_ROUTE);
- if (nl_socket_msg <= 0) {
- LOGE("Can not create netlink msg socket");
- goto error;
- }
- if (bind(nl_socket_msg, (struct sockaddr *)(&addr_msg),
- sizeof(struct sockaddr_nl))) {
- LOGE("Can not bind to netlink msg socket");
- goto error;
- }
- nl_socket_poll = socket(AF_NETLINK,SOCK_RAW,NETLINK_ROUTE);
- if (nl_socket_poll <= 0) {
- LOGE("Can not create netlink poll socket");
- goto error;
- }
- errno = 0;
- if (bind(nl_socket_poll, (struct sockaddr *)(&addr_poll),
- sizeof(struct sockaddr_nl))) {
- LOGE("Can not bind to netlink poll socket,%s", strerror(errno));
- goto error;
- }
- if ((ret = netlink_init_interfaces_list()) < 0) {
- LOGE("Can not collect the interface list");
- goto error;
- }
- LOGE("%s exited with success", __FUNCTION__);
- return ret;
- error:
- LOGE("%s exited with error", __FUNCTION__);
- if (nl_socket_msg > 0)
- close(nl_socket_msg);
- if (nl_socket_poll > 0)
- close(nl_socket_poll);
- return ret;
- }
- </PRE><SPAN style="COLOR: #ff0000; FONT-SIZE: 16px"><STRONG><BR>
- 6. getInterfaceName() 和 getInterfaceCnt():</STRONG></SPAN><BR>
- <PRE class=cpp name="code"> static jstring android_net_ethernet_getInterfaceName(JNIEnv *env,
- jobject clazz,
- jint index)
- {
- int i = 0;
- interface_info_t *info;
- LOGI("User ask for device name on %d, list:%X, total:%d",
- index, (unsigned int)interfaces, total_int);
- info = interfaces;
- if (total_int != 0 && index <= (total_int - 1)) {
- while (info) {
- if (index == i) {
- LOGV("Found: %s", info->name);
- return env->NewStringUTF(info->name);
- }
- info = info->next;
- i++;
- }
- }
- LOGI("No device name found");
- return env->NewStringUTF(NULL);
- }
- static jint android_net_ethernet_getInterfaceCnt()
- {
- return total_int;
- }
- </PRE><BR>
- <BR>
- <PRE></PRE>
- <P></P>
- <P></P>
- <PRE></PRE>
- <SPAN style="COLOR: #ff0000"><STRONG><SPAN style="FONT-SIZE: 16px"><BR>
- </SPAN></STRONG></SPAN>
- <P></P>
- <PRE></PRE>
- <PRE></PRE>
- <PRE></PRE>
检测 android ethernet 支持 IPV6 否
如果路由器或交换机不支持IPv6, 则把开发板与PC直连。现在的phy应该都支持直连,不许要特定交叉或直连线了。
1. busybox ifconfig -a : 查看本地IPV6 地址
- root@android:/ # busybox ifconfig -a
- eth0 Link encap:Ethernet HWaddr 00:80:E1:12:64:5F
- inet6 addr: fec0:1111:2222:3333:280:e1ff:fe12:645f/64 Scope:Site
- inet6 addr: fe80::280:e1ff:fe12:645f/64 Scope:Link
- UP BROADCAST MULTICAST MTU:1500 Metric:1
- RX packets:223 errors:0 dropped:0 overruns:0 frame:0
- TX packets:31 errors:0 dropped:0 overruns:0 carrier:0
- collisions:0 txqueuelen:1000
- RX bytes:39851 (38.9 KiB) TX bytes:8561 (8.3 KiB)
- Interrupt:179
- lo Link encap:Local Loopback
- inet addr:127.0.0.1 Mask:255.0.0.0
- inet6 addr: ::1/128 Scope:Host
- UP LOOPBACK RUNNING MTU:16436 Metric:1
- RX packets:464 errors:0 dropped:0 overruns:0 frame:0
- TX packets:464 errors:0 dropped:0 overruns:0 carrier:0
- collisions:0 txqueuelen:0
- RX bytes:34144 (33.3 KiB) TX bytes:34144 (33.3 KiB)
- sit0 Link encap:IPv6-in-IPv4
- NOARP MTU:1480 Metric:1
- RX packets:0 errors:0 dropped:0 overruns:0 frame:0
- TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
- collisions:0 txqueuelen:0
- RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
root@android:/ # busybox ifconfig -a
eth0 Link encap:Ethernet HWaddr 00:80:E1:12:64:5F
inet6 addr: fec0:1111:2222:3333:280:e1ff:fe12:645f/64 Scope:Site
inet6 addr: fe80::280:e1ff:fe12:645f/64 Scope:Link
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:223 errors:0 dropped:0 overruns:0 frame:0
TX packets:31 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:39851 (38.9 KiB) TX bytes:8561 (8.3 KiB)
Interrupt:179
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:464 errors:0 dropped:0 overruns:0 frame:0
TX packets:464 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:34144 (33.3 KiB) TX bytes:34144 (33.3 KiB)
sit0 Link encap:IPv6-in-IPv4
NOARP MTU:1480 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
inet6 addr : 就是IPv6 IP地址. 如果没有安装radvd, 第一行inet6 addr 是不会出现的。
2. ping6 -I eth0 fe80::280:e1ff:fe12:645f
或 ping6 fe80::280:e1ff:fe12:645f%eth0
检查是否能ping通,如果ping通了,就可以进行下一步了。
这里ping6时,需指定eth0 接口,要不然是ping6不通的。
3. 在unbuntu PC上安装apache:
sudo apt-get install apache2 :安装apache。
sudo /etc/init.d/apache2 restart :启动apache。
sudo vim /var/www/index.html : 修改网页内容。
在firefox中打开网页
http://localhost/
http://本地ipv4地址/
可以检测apache是否工作正常
这时用 http://本地ipv6地址/ 是不能打开网页的,还需要以下几步。
4. 安装dhcpv6 server 和 client:
sudo apt-get install wide-dhcpv6-client wide-dhcpv6-server
这里client应该可以不装。
5. 安装玩 radvd:
这里安装玩 dhcpv6还不够,还需要安装radvd.
a. sudo apt-get install radvd
b. vi /etc/radvd.conf(需新建该文件),如下面几行:
- interface eth0 {
- MinRtrAdvInterval 3;
- MaxRtrAdvInterval 10;
- AdvLinkMTU 1280;
- AdvSendAdvert on;
- prefixfec0:1111:2222:3333::/64 {
- AdvOnLinkon;
- AdvAutonomous on;
- AdvValidLifetime 86400;
- AdvPreferredLifetime 86400;
- AdvRouterAddr on;
- };
- };
interface eth0 {
MinRtrAdvInterval 3;
MaxRtrAdvInterval 10;
AdvLinkMTU 1280;
AdvSendAdvert on;
prefixfec0:1111:2222:3333::/64 {
AdvOnLinkon;
AdvAutonomous on;
AdvValidLifetime 86400;
AdvPreferredLifetime 86400;
AdvRouterAddr on;
};
};
c. 在/etc/sysctl.conf 中打开 net.ipv6.conf.all.forwarding=1
d. sudo /etc/init.d/radvd start
(如果在 radvd 运行状态下重启机器,radvd 会在开机后自动运行)
6. 这时在PC 的 firefox 中打开 apache 网页内容就可以了。
http://[fec0:1111:2222:3333:baac:6fff:fe3e:5af8]/
在 开发板的 web browser 中也可以通过IPv6打开PC apache内容, 地址栏同样是: