| Kiss driver modification to immediately start in FLEX_CRC modeKiss driver (mkiss.c source in /usr/src/linux/driver/net/hamradio) is programmed to start in normal kiss mode.As soon as it receive a frame, it analyze the first byte of encapsulated kiss frame to detect if a CRC have been used: possible CRC are Flexnet (RMNC) and SMACK. Why a modification to the driver is needed? In my case, i'm using a SuperVozelj node as TNC, which has the Flexnet_CRC capability to stat if a frame is good or corrupted, so the SuperVozelj RS232 port is configured in this mode. Without the driver modification suggested below, as soon as i boot my Linux PC the KISS driver start in normal KISS mode, without CRC, so every frame to the SuperVozelj will be transmitted in KISS mode: all frames will be rejected by the SuperVozelj because they don't contains Flexnet CRC!. This problem occurred until a frame will be received by the Linux driver (for example the beacon transmitted by the SuperVozelj every 5 minutes): in this case, mkiss driver stats that this is a Flexnet_CRC frame, and it switch to operate in this CRC mode. The modification applied (in the source /usr/src/linux/driver/net/hamradio/mkiss.c) permit to start, by default, in Flexnet CRC mode: only one line must be added to the source!. /* Initialize the driver. Called by network startup. */ static int ax25_init(struct net_device *dev) { struct ax_disp *ax = (struct ax_disp *) dev->priv; static char ax25_bcast[AX25_ADDR_LEN] = {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1}; static char ax25_test[AX25_ADDR_LEN] = {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1}; if (ax == NULL) /* Allocation failed ?? */ return -ENODEV; /* Set up the "AX25 Control Block". (And clear statistics) */ memset(ax, 0, sizeof (struct ax_disp)); ax->magic = AX25_MAGIC; ax->dev = dev; ax->crcmode = CRC_MODE_FLEX; // added by iw3grx to setup CRC_MODE /* Finish setting up the DEVICE info. */ dev->mtu = AX_MTU; dev->hard_start_xmit = ax_xmit; dev->open = ax_open_dev; Linux kernel modifications to get iso-interface ip-forwardingAmateur radio network is not easy connectable: sometimes in the same lan there are hamradio hosts from several countries, which are connected to a central ip router throught our AX.25 level2 network using several bridges (here we are using SuperVozelj nodes, with 38400/1228800bps links, and very often i see ham hosts from Italy, Slovenia and Croatia).Now is clear that our Local Area Network is not so local as we see in normal cabled LANs, and usually each host in the lan uses the nearest router as gateway to reach other hosts in the LAN. With 2.0.x kernel there were no problems, but in the 2.2.x kernel the iso-interface ip forwarding was disabled. Ivan 9a3wn suggest me the modifications for the Linux 2.2.x kernel, which now i will explain. Enter linux kernel directory (usually with cd /usr/src/linux command), and then edit the file net/ax25/ax25_in.c, for example with the command joe net/ax25/ax25_in.c You must add 3 lines, marked below in bold font:
..........
#ifdef CONFIG_INET if (pid == AX25_P_IP) { /* working around a TCP bug to keep additional listeners * happy. TCP re-uses the buffer and destroys the original * content. */ struct sk_buff *skbn = skb_copy(skb, GFP_ATOMIC); if (skbn != NULL) { kfree_skb(skb); skb = skbn; } skb_pull(skb, 1); /* Remove PID */ skb->h.raw = skb->data; skb->nh.raw = skb->data; skb->dev = ax25->ax25_dev->dev; skb->pkt_type = PACKET_HOST; skb->protocol = __constant_htons(ETH_P_IP); // added for iso-interface forwarding ip_rcv(skb, skb->dev, NULL); /* Wrong ptype */ return 1; } #endif........... #ifdef CONFIG_INET case AX25_P_IP: skb_pull(skb,2); /* drop PID/CTRL */ skb->h.raw = skb->data; skb->nh.raw = skb->data; skb->dev = dev; skb->pkt_type = PACKET_HOST; skb->protocol = __constant_htons(ETH_P_IP); // added for iso-iface fwd ip_rcv(skb, dev, ptype); /* Note ptype here is the wrong one, fix me later */ break; case AX25_P_ARP: skb_pull(skb,2); skb->h.raw = skb->data; skb->nh.raw = skb->data; skb->dev = dev; skb->pkt_type = PACKET_HOST; skb->protocol = __constant_htons(ETH_P_ARP); // added for iso-iface fwd arp_rcv(skb, dev, ptype); /* Note ptype here is wrong... */ break; #endif.......... Modifications to ax25 route daemonThis modification is intended to permit ax25 route daemon to automatically add route/arp entries in the route/arp tables for hosts that are not inside the network mask.Infact, in the normal configuration ax25rtd only update route/arp table for hosts that are inside the netmask of the interface which receive the ip datagrams, but this is not a good solution for routers that receive datagrams from Italy, Slovenia and Croatia as my router does, because the radio interface netmask must be as closed as possible: infact many hosts are connectable throught the internet ham gateway 44.0.0.1. The modification to the ax25rtd is very simple: at the bootstrap, the daemon must NOT load the interface netmask, but the netmask 255.0.0.0 (which cover all the amateur radio hosts): the silly modification is indicated below in bold font, and must be made in the ax25-apps-0.0.4/ax25rtd/config.c file:
.........
for (config = Config; config; config = config->next) if (!memcmp(&config->mycalls[0], ifr.ifr_hwaddr.sa_data, AXLEN) && !*config->dev) { strcpy(config->dev, ifr.ifr_name); ioctl(fd, SIOCGIFADDR, &ifr); config->ip = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr; strcpy(ifr.ifr_name, config->dev); ioctl(fd, SIOCGIFNETMASK, &ifr); // instead of loading interface netmask, load 255.0.0.0 to cover all the 44.0.0.0/8 network! // config->netmask = ((struct sockaddr_in *) &ifr.ifr_netmask)->sin_addr.s_addr; config->netmask = 0x0000ff; break; } } close(fd); config = cfg = Config;........... Modifications to the kernel mkiss driverWhy? Because i need to know how many bytes of data was RXed and TXed by kiss/crckiss ports.This is useful for certain statistics programs, like MRTG, a very nice port load statistics report for the web. First, cd to /usr/src/linux/driver/net/hamradio and then add the lines indicated with bold font to the file mkiss.h: /* SLIP interface statistics. */ unsigned long rx_packets; /* inbound frames counter */ unsigned long tx_packets; /* outbound frames counter */ unsigned long rx_bytes; // inbound octets counter unsigned long tx_bytes; // outbound octets counter unsigned long rx_errors; /* Parity, etc. errors */ unsigned long tx_errors; /* Planned stuff */ unsigned long rx_dropped; /* No memory for skb */ unsigned long tx_dropped; /* When MTU change */ unsigned long rx_over_errors; /* Frame bigger then SLIP buf. */ static void ax_bump(struct ax_disp *ax) { ............ } count = ax->rcount; ax->rx_bytes+=count; if ((skb = dev_alloc_skb(count)) == NULL) { printk(KERN_ERR "mkiss: %s: memory squeeze, dropping packet.\n", ax->dev->name); ........... /* Encapsulate an AX.25 packet and kick it into a TTY queue. */ static int ax_xmit(struct sk_buff *skb, struct device *dev) { ............ /* We were not busy, so we are now... :-) */ if (skb != NULL) { ax_lock(ax); if (tmp_ax != NULL) ax_lock(tmp_ax); ax->tx_bytes+=skb->len; ax_encaps(ax, skb->data, skb->len); kfree_skb(skb); } return 0; } .......... static struct net_device_stats *ax_get_stats(struct device *dev) { static struct net_device_stats stats; struct ax_disp *ax = (struct ax_disp*)(dev->priv); memset(&stats, 0, sizeof(struct net_device_stats)); stats.rx_packets = ax->rx_packets; stats.tx_packets = ax->tx_packets; stats.rx_bytes = ax->rx_bytes; stats.tx_bytes = ax->tx_bytes; stats.rx_dropped = ax->rx_dropped; stats.tx_dropped = ax->tx_dropped; stats.tx_errors = ax->tx_errors; stats.rx_errors = ax->rx_errors; stats.rx_over_errors = ax->rx_over_errors; return &stats; } cd /usr/src/linux && make dep && make bzImage && make modules && make modules_install Modifications to netromd daemon to permit routing with X-NetXnet nodes send netrom broadcasts to the callsign of the neighbour node, instead to NODES. This is the reason why netromd does not store in its nodes list the nodes received from a X-Net neighbour.To avoid this problem there are two solutions:
|