Merge branch 'net-next-3.10'
diff --git a/bridge/fdb.c b/bridge/fdb.c
index 6aa5d0a..591fbbe 100644
--- a/bridge/fdb.c
+++ b/bridge/fdb.c
@@ -30,8 +30,8 @@
 
 static void usage(void)
 {
-	fprintf(stderr, "Usage: bridge fdb { add | del } ADDR dev DEV {self|master} [ temp ] [router]\n"
-		        "              [ dst IPADDR] [ vlan VID ]\n"
+	fprintf(stderr, "Usage: bridge fdb { add | append | del } ADDR dev DEV {self|master} [ temp ]\n"
+		        "              [router] [ dst IPADDR] [ vlan VID ]\n"
 		        "              [ port PORT] [ vni VNI ] [via DEV]\n");
 	fprintf(stderr, "       bridge fdb {show} [ dev DEV ]\n");
 	exit(-1);
diff --git a/include/SNAPSHOT.h b/include/SNAPSHOT.h
index dd53a9c..63b857d 100644
--- a/include/SNAPSHOT.h
+++ b/include/SNAPSHOT.h
@@ -1 +1 @@
-static const char SNAPSHOT[] = "130430";
+static const char SNAPSHOT[] = "130716";
diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h
index 6a48d55..0da6f5e 100644
--- a/include/linux/if_arp.h
+++ b/include/linux/if_arp.h
@@ -93,6 +93,7 @@
 #define ARPHRD_PHONET_PIPE 821		/* PhoNet pipe header		*/
 #define ARPHRD_CAIF	822		/* CAIF media type		*/
 #define ARPHRD_IP6GRE	823		/* GRE over IPv6		*/
+#define ARPHRD_NETLINK	824		/* Netlink header		*/
 
 #define ARPHRD_VOID	  0xFFFF	/* Void type, nothing is known */
 #define ARPHRD_NONE	  0xFFFE	/* zero header length */
diff --git a/include/utils.h b/include/utils.h
index 2bd8c62..24ff19f 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -19,6 +19,7 @@
 extern int timestamp;
 extern char * _SL_;
 extern int max_flush_loops;
+extern int batch_mode;
 
 #ifndef IPPROTO_ESP
 #define IPPROTO_ESP	50
diff --git a/ip/ip.c b/ip/ip.c
index 69bd5ff..86f8b45 100644
--- a/ip/ip.c
+++ b/ip/ip.c
@@ -30,9 +30,9 @@
 int oneline = 0;
 int timestamp = 0;
 char * _SL_ = NULL;
-char *batch_file = NULL;
 int force = 0;
 int max_flush_loops = 10;
+int batch_mode = 0;
 
 struct rtnl_handle rth = { .fd = -1 };
 
@@ -113,6 +113,8 @@
 	size_t len = 0;
 	int ret = EXIT_SUCCESS;
 
+	batch_mode = 1;
+
 	if (name && strcmp(name, "-") != 0) {
 		if (freopen(name, "r", stdin) == NULL) {
 			fprintf(stderr, "Cannot open file \"%s\" for reading: %s\n",
@@ -153,6 +155,7 @@
 int main(int argc, char **argv)
 {
 	char *basename;
+	char *batch_file = NULL;
 
 	basename = strrchr(argv[0], '/');
 	if (basename == NULL)
diff --git a/ip/iplink_vlan.c b/ip/iplink_vlan.c
index ed8984a..94b52ae 100644
--- a/ip/iplink_vlan.c
+++ b/ip/iplink_vlan.c
@@ -21,9 +21,11 @@
 static void explain(void)
 {
 	fprintf(stderr,
-		"Usage: ... vlan id VLANID [ FLAG-LIST ]\n"
-		"                          [ ingress-qos-map QOS-MAP ] [ egress-qos-map QOS-MAP ]\n"
+		"Usage: ... vlan [ protocol VLANPROTO ] id VLANID"
+		"                [ FLAG-LIST ]\n"
+		"                [ ingress-qos-map QOS-MAP ] [ egress-qos-map QOS-MAP ]\n"
 		"\n"
+		"VLANPROTO: [ 802.1Q / 802.1ad ]\n"
 		"VLANID := 0-4095\n"
 		"FLAG-LIST := [ FLAG-LIST ] FLAG\n"
 		"FLAG := [ reorder_hdr { on | off } ] [ gvrp { on | off } ] [ mvrp { on | off } ]\n"
@@ -77,10 +79,15 @@
 			  struct nlmsghdr *n)
 {
 	struct ifla_vlan_flags flags = { 0 };
-	__u16 id;
+	__u16 id, proto;
 
 	while (argc > 0) {
-		if (matches(*argv, "id") == 0) {
+		if (matches(*argv, "protocol") == 0) {
+			NEXT_ARG();
+			if (ll_proto_a2n(&proto, *argv))
+				invarg("protocol is invalid", *argv);
+			addattr_l(n, 1024, IFLA_VLAN_PROTOCOL, &proto, 2);
+		} else if (matches(*argv, "id") == 0) {
 			NEXT_ARG();
 			if (get_u16(&id, *argv, 0))
 				invarg("id is invalid", *argv);
@@ -186,13 +193,25 @@
 static void vlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
 {
 	struct ifla_vlan_flags *flags;
+	SPRINT_BUF(b1);
+
 	if (!tb)
 		return;
 
+	if (tb[IFLA_VLAN_PROTOCOL] &&
+	    RTA_PAYLOAD(tb[IFLA_VLAN_PROTOCOL]) < sizeof(__u16))
+		return;
 	if (!tb[IFLA_VLAN_ID] ||
 	    RTA_PAYLOAD(tb[IFLA_VLAN_ID]) < sizeof(__u16))
 		return;
 
+	if (tb[IFLA_VLAN_PROTOCOL])
+		fprintf(f, "protocol %s ",
+			ll_proto_n2a(rta_getattr_u16(tb[IFLA_VLAN_PROTOCOL]),
+				     b1, sizeof(b1)));
+	else
+		fprintf(f, "protocol 802.1q ");
+
 	fprintf(f, "id %u ", rta_getattr_u16(tb[IFLA_VLAN_ID]));
 
 	if (tb[IFLA_VLAN_FLAGS]) {
diff --git a/ip/ipnetns.c b/ip/ipnetns.c
index fa2b681..794a498 100644
--- a/ip/ipnetns.c
+++ b/ip/ipnetns.c
@@ -42,7 +42,6 @@
 #define MS_SHARED	(1 << 20)
 #endif
 
-
 #ifndef HAVE_SETNS
 static int setns(int fd, int nstype)
 {
@@ -64,7 +63,7 @@
 	fprintf(stderr, "       ip netns pids NAME\n");
 	fprintf(stderr, "       ip netns exec NAME cmd ...\n");
 	fprintf(stderr, "       ip netns monitor\n");
-	return EXIT_FAILURE;
+	exit(-1);
 }
 
 int get_netns_fd(const char *name)
@@ -89,7 +88,7 @@
 
 	dir = opendir(NETNS_RUN_DIR);
 	if (!dir)
-		return EXIT_SUCCESS;
+		return 0;
 
 	while ((entry = readdir(dir)) != NULL) {
 		if (strcmp(entry->d_name, ".") == 0)
@@ -99,7 +98,7 @@
 		printf("%s\n", entry->d_name);
 	}
 	closedir(dir);
-	return EXIT_SUCCESS;
+	return 0;
 }
 
 static void bind_etc(const char *name)
@@ -141,12 +140,13 @@
 
 	if (argc < 1) {
 		fprintf(stderr, "No netns name specified\n");
-		return EXIT_FAILURE;
+		return -1;
 	}
 	if (argc < 2) {
 		fprintf(stderr, "No command specified\n");
-		return EXIT_FAILURE;
+		return -1;
 	}
+
 	name = argv[0];
 	cmd = argv[1];
 	snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name);
@@ -154,41 +154,69 @@
 	if (netns < 0) {
 		fprintf(stderr, "Cannot open network namespace \"%s\": %s\n",
 			name, strerror(errno));
-		return EXIT_FAILURE;
+		return -1;
 	}
+
 	if (setns(netns, CLONE_NEWNET) < 0) {
 		fprintf(stderr, "seting the network namespace \"%s\" failed: %s\n",
 			name, strerror(errno));
-		return EXIT_FAILURE;
+		return -1;
 	}
 
 	if (unshare(CLONE_NEWNS) < 0) {
 		fprintf(stderr, "unshare failed: %s\n", strerror(errno));
-		return EXIT_FAILURE;
+		return -1;
 	}
 	/* Don't let any mounts propogate back to the parent */
 	if (mount("", "/", "none", MS_SLAVE | MS_REC, NULL)) {
 		fprintf(stderr, "\"mount --make-rslave /\" failed: %s\n",
 			strerror(errno));
-		return EXIT_FAILURE;
+		return -1;
 	}
 	/* Mount a version of /sys that describes the network namespace */
 	if (umount2("/sys", MNT_DETACH) < 0) {
 		fprintf(stderr, "umount of /sys failed: %s\n", strerror(errno));
-		return EXIT_FAILURE;
+		return -1;
 	}
 	if (mount(name, "/sys", "sysfs", 0, NULL) < 0) {
 		fprintf(stderr, "mount of /sys failed: %s\n",strerror(errno));
-		return EXIT_FAILURE;
+		return -1;
 	}
 
 	/* Setup bind mounts for config files in /etc */
 	bind_etc(name);
 
+	fflush(stdout);
+
+	if (batch_mode) {
+		int status;
+		pid_t pid;
+
+		pid = fork();
+		if (pid < 0) {
+			perror("fork");
+			exit(1);
+		}
+
+		if (pid != 0) {
+			/* Parent  */
+			if (waitpid(pid, &status, 0) < 0) {
+				perror("waitpid");
+				exit(1);
+			}
+
+			/* If child failed, propogate status */
+			if (WIFEXITED(status))
+				exit(WEXITSTATUS(status));
+
+			return 0;
+		}
+	}
+
 	if (execvp(cmd, argv + 1)  < 0)
 		fprintf(stderr, "exec of \"%s\" failed: %s\n",
 			cmd, strerror(errno));
-	return EXIT_FAILURE;
+	_exit(1);
 }
 
 static int is_pid(const char *str)
@@ -212,11 +240,11 @@
 
 	if (argc < 1) {
 		fprintf(stderr, "No netns name specified\n");
-		return EXIT_FAILURE;
+		return -1;
 	}
 	if (argc > 1) {
 		fprintf(stderr, "extra arguments specified\n");
-		return EXIT_FAILURE;
+		return -1;
 	}
 
 	name = argv[0];
@@ -225,18 +253,18 @@
 	if (netns < 0) {
 		fprintf(stderr, "Cannot open network namespace: %s\n",
 			strerror(errno));
-		return EXIT_FAILURE;
+		return -1;
 	}
 	if (fstat(netns, &netst) < 0) {
 		fprintf(stderr, "Stat of netns failed: %s\n",
 			strerror(errno));
-		return EXIT_FAILURE;
+		return -1;
 	}
 	dir = opendir("/proc/");
 	if (!dir) {
 		fprintf(stderr, "Open of /proc failed: %s\n",
 			strerror(errno));
-		return EXIT_FAILURE;
+		return -1;
 	}
 	while((entry = readdir(dir))) {
 		char pid_net_path[MAXPATHLEN];
@@ -253,7 +281,7 @@
 		}
 	}
 	closedir(dir);
-	return EXIT_SUCCESS;
+	return 0;
 	
 }
 
@@ -268,18 +296,18 @@
 
 	if (argc < 1) {
 		fprintf(stderr, "No pid specified\n");
-		return EXIT_FAILURE;
+		return -1;
 	}
 	if (argc > 1) {
 		fprintf(stderr, "extra arguments specified\n");
-		return EXIT_FAILURE;
+		return -1;
 	}
 	pidstr = argv[0];
 
 	if (!is_pid(pidstr)) {
 		fprintf(stderr, "Specified string '%s' is not a pid\n",
 			pidstr);
-		return EXIT_FAILURE;
+		return -1;
 	}
 
 	snprintf(net_path, sizeof(net_path), "/proc/%s/ns/net", pidstr);
@@ -287,22 +315,22 @@
 	if (netns < 0) {
 		fprintf(stderr, "Cannot open network namespace: %s\n",
 			strerror(errno));
-		return EXIT_FAILURE;
+		return -1;
 	}
 	if (fstat(netns, &netst) < 0) {
 		fprintf(stderr, "Stat of netns failed: %s\n",
 			strerror(errno));
-		return EXIT_FAILURE;
+		return -1;
 	}
 	dir = opendir(NETNS_RUN_DIR);
 	if (!dir) {
 		/* Succeed treat a missing directory as an empty directory */
 		if (errno == ENOENT)
-			return EXIT_SUCCESS;
+			return 0;
 
 		fprintf(stderr, "Failed to open directory %s:%s\n",
 			NETNS_RUN_DIR, strerror(errno));
-		return EXIT_FAILURE;
+		return -1;
 	}
 
 	while((entry = readdir(dir))) {
@@ -326,7 +354,7 @@
 		}
 	}
 	closedir(dir);
-	return EXIT_SUCCESS;
+	return 0;
 	
 }
 
@@ -337,7 +365,7 @@
 
 	if (argc < 1) {
 		fprintf(stderr, "No netns name specified\n");
-		return EXIT_FAILURE;
+		return -1;
 	}
 
 	name = argv[0];
@@ -346,9 +374,9 @@
 	if (unlink(netns_path) < 0) {
 		fprintf(stderr, "Cannot remove namespace file \"%s\": %s\n",
 			netns_path, strerror(errno));
-		return EXIT_FAILURE;
+		return -1;
 	}
-	return EXIT_SUCCESS;
+	return 0;
 }
 
 static int netns_add(int argc, char **argv)
@@ -368,7 +396,7 @@
 
 	if (argc < 1) {
 		fprintf(stderr, "No netns name specified\n");
-		return EXIT_FAILURE;
+		return -1;
 	}
 	name = argv[0];
 
@@ -388,14 +416,14 @@
 		if (errno != EINVAL || made_netns_run_dir_mount) {
 			fprintf(stderr, "mount --make-shared %s failed: %s\n",
 				NETNS_RUN_DIR, strerror(errno));
-			return EXIT_FAILURE;
+			return -1;
 		}
 
 		/* Upgrade NETNS_RUN_DIR to a mount point */
 		if (mount(NETNS_RUN_DIR, NETNS_RUN_DIR, "none", MS_BIND, NULL)) {
 			fprintf(stderr, "mount --bind %s %s failed: %s\n",
 				NETNS_RUN_DIR, NETNS_RUN_DIR, strerror(errno));
-			return EXIT_FAILURE;
+			return -1;
 		}
 		made_netns_run_dir_mount = 1;
 	}
@@ -405,7 +433,7 @@
 	if (fd < 0) {
 		fprintf(stderr, "Cannot not create namespace file \"%s\": %s\n",
 			netns_path, strerror(errno));
-		return EXIT_FAILURE;
+		return -1;
 	}
 	close(fd);
 	if (unshare(CLONE_NEWNET) < 0) {
@@ -420,10 +448,10 @@
 			netns_path, strerror(errno));
 		goto out_delete;
 	}
-	return EXIT_SUCCESS;
+	return 0;
 out_delete:
 	netns_delete(argc, argv);
-	return EXIT_FAILURE;
+	return -1;
 }
 
 
@@ -436,19 +464,19 @@
 	if (fd < 0) {
 		fprintf(stderr, "inotify_init failed: %s\n",
 			strerror(errno));
-		return EXIT_FAILURE;
+		return -1;
 	}
 	if (inotify_add_watch(fd, NETNS_RUN_DIR, IN_CREATE | IN_DELETE) < 0) {
 		fprintf(stderr, "inotify_add_watch failed: %s\n",
 			strerror(errno));
-		return EXIT_FAILURE;
+		return -1;
 	}
 	for(;;) {
 		ssize_t len = read(fd, buf, sizeof(buf));
 		if (len < 0) {
 			fprintf(stderr, "read failed: %s\n",
 				strerror(errno));
-			return EXIT_FAILURE;
+			return -1;
 		}
 		for (event = (struct inotify_event *)buf;
 		     (char *)event < &buf[len];
@@ -459,7 +487,7 @@
 				printf("delete %s\n", event->name);
 		}
 	}
-	return EXIT_SUCCESS;
+	return 0;
 }
 
 int do_netns(int argc, char **argv)
@@ -493,5 +521,5 @@
 		return netns_monitor(argc-1, argv+1);
 
 	fprintf(stderr, "Command \"%s\" is unknown, try \"ip netns help\".\n", *argv);
-	return EXIT_FAILURE;
+	exit(-1);
 }
diff --git a/ip/iproute.c b/ip/iproute.c
index 46710b2..b069f1e 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -1341,7 +1341,7 @@
 
 			if (time(0) - start > 30) {
 				printf("\n*** Flush not completed after %ld seconds, %d entries remain ***\n",
-				       time(0) - start, filter.flushed);
+				       (long)(time(0) - start), filter.flushed);
 				exit(1);
 			}
 
diff --git a/ip/iptunnel.c b/ip/iptunnel.c
index 4275f26..43f8585 100644
--- a/ip/iptunnel.c
+++ b/ip/iptunnel.c
@@ -341,7 +341,7 @@
 	       p->iph.daddr ? format_host(AF_INET, 4, &p->iph.daddr, s1, sizeof(s1))  : "any",
 	       p->iph.saddr ? rt_addr_n2a(AF_INET, 4, &p->iph.saddr, s2, sizeof(s2)) : "any");
 
-	if (p->i_flags & SIT_ISATAP) {
+	if (p->iph.protocol == IPPROTO_IPV6 && (p->i_flags & SIT_ISATAP)) {
 		struct ip_tunnel_prl prl[16];
 		int i;
 		
diff --git a/lib/ll_proto.c b/lib/ll_proto.c
index 3aa8252..d8df68c 100644
--- a/lib/ll_proto.c
+++ b/lib/ll_proto.c
@@ -78,6 +78,8 @@
 __PF(ECONET,econet)
 __PF(TIPC,tipc)
 __PF(AOE,aoe)
+__PF(8021Q,802.1Q)
+__PF(8021AD,802.1ad)
 
 { 0x8100, "802.1Q" },
 { 0x88cc, "LLDP" },
diff --git a/man/man8/bridge.8 b/man/man8/bridge.8
index 9be0c20..66678b5 100644
--- a/man/man8/bridge.8
+++ b/man/man8/bridge.8
@@ -44,12 +44,20 @@
 .IR DEV " ]"
 
 .ti -8
-.BR "bridge fdb" " { " add " | " del " } "
+.BR "bridge fdb" " { " add " | " append " | " del " } "
 .I LLADDR
 .B  dev
 .IR DEV " { "
 .BR local " | " temp " } { "
-.BR self " } { " embedded " } "
+.BR self " } { " embedded " } { " router " } [ "
+.B  dst
+.IR IPADDR " ] [ "
+.B vni
+.IR VNI " ] ["
+.B port
+.IR PORT " ] ["
+.B via
+.IR DEVICE " ]"
 
 .ti -8
 .BR "bridge fdb" " [ " show " ] [ "
@@ -229,6 +237,7 @@
 
 .P
 The corresponding commands display fdb entries, add new entries,
+append entries,
 and delete old ones.
 
 .SS bridge fdb add - add a new fdb entry
@@ -236,11 +245,11 @@
 This command creates a new fdb entry.
 
 .TP
-.BI "ADDRESS"
+.BI "LLADDR"
 the Ethernet MAC address.
 
 .TP
-.BI dev " NAME"
+.BI dev " DEV"
 the interface to which this address is associated.
 
 .B self
@@ -251,7 +260,54 @@
 - the address is associated with an offloaded fdb
 .sp
 
+.B router
+- the destination address is associated with a router.
+Valid if the referenced device is a VXLAN type device and has
+route shortcircuit enabled.
+.sp
+
 .in -8
+The next command line parameters apply only
+when the specified device
+.I DEV
+is of type VXLAN.
+.TP
+.BI dst " IPADDR"
+the IP address of the destination
+VXLAN tunnel endpoint where the Ethernet MAC ADDRESS resides.
+
+.TP
+.BI vni " VNI"
+the VXLAN VNI Network Identifier (or VXLAN Segment ID)
+to use to connect to the remote VXLAN tunnel endpoint.
+If omitted the value specified at vxlan device creation
+will be used.
+
+.TP
+.BI port " PORT"
+the UDP destination PORT number to use to connect to the
+remote VXLAN tunnel endpoint.
+If omitted the default value is used.
+
+.TP
+.BI via " DEVICE"
+device name of the outgoing interface for the
+VXLAN device driver to reach the
+remote VXLAN tunnel endpoint. 
+
+.SS bridge fdb append - append a forwarding database entry
+This command adds a new fdb entry with an already known
+.IR LLADDR .
+Valid only for multicast link layer addresses.
+The command adds support for broadcast and multicast
+Ethernet MAC addresses.
+The Ethernet MAC address is added multiple times into
+the forwarding database and the vxlan device driver
+sends a copy of the data packet to each entry found.
+
+.PP
+The arguments are the same as with
+.BR "bridge fdb add" ,
 
 .SS bridge fdb delete - delete a forwarding database entry
 This command removes an existing fdb entry.
diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in
index 2e89efe..86e0bc9 100644
--- a/man/man8/ip-link.8.in
+++ b/man/man8/ip-link.8.in
@@ -196,6 +196,91 @@
 .BI numrxqueues " QUEUE_COUNT "
 specifies the number of receive queues for new device.
 
+.TP
+VXLAN Type Support
+For a link of type 
+.I VXLAN
+the following additional arguments are supported:
+
+.BI "ip link add " DEVICE
+.BI type " vxlan " id " ID
+.R " [ "
+.BI dev " PHYS_DEV "
+.R " ] [ "
+.BI group " IPADDR "
+.R " ] [ "
+.BI local " IPADDR "
+.R " ] [ "
+.BI ttl " TTL "
+.R " ] [ "
+.BI tos " TOS "
+.R " ] [ "
+.BI port " MIN MAX "
+.R " ] [ "
+.I "[no]learning "
+.R " ] [ "
+.I "[no]proxy "
+.R " ] [ "
+.I "[no]rsc "
+.R " ] [ "
+.I "[no]l2miss "
+.R " ] [ "
+.I "[no]l3miss "
+.R " ]"
+
+.in +8
+.sp
+.BI  id " VNI "
+- specifies the VXLAN Network Identifer (or VXLAN Segment
+Identifier) to use.
+
+.BI dev " PHYS_DEV"
+- specifies the physical device to use for tunnel endpoint communication.
+
+.sp
+.BI group " IPADDR"
+- specifies the multicast IP address to join.
+
+.sp
+.BI local " IPADDR"
+- specifies the source IP address to use in outgoing packets.
+
+.sp
+.BI ttl " TTL"
+- specifies the TTL value to use in outgoing packets.
+
+.sp
+.BI tos " TOS"
+- specifies the TOS value to use in outgoing packets.
+
+.sp
+.BI port " MIN MAX"
+- specifies the range of port numbers to use as UDP
+source ports to communicate to the remote VXLAN tunnel endpoint.
+
+.sp
+.I [no]learning
+- specifies if unknown source link layer addresses and IP addresses
+are entered into the VXLAN device forwarding database.
+
+.sp
+.I [no]rsc
+- specifies if route short circuit is turned on.
+
+.sp
+.I [no]proxy
+- specifies ARP proxy is turned on.
+
+.sp
+.I [no]l2miss
+- specifies if netlink LLADDR miss notifications are generated.
+
+.sp
+.I [no]l3miss
+- specifies if netlink IP ADDR miss notifications are generated.
+
+.in -8
+
 .SS ip link delete - delete virtual link
 .I DEVICE
 specifies the virtual  device to act operate on.
diff --git a/man/man8/ip-maddress.8 b/man/man8/ip-maddress.8
index e0bad47..288d5cc 100644
--- a/man/man8/ip-maddress.8
+++ b/man/man8/ip-maddress.8
@@ -31,13 +31,17 @@
 .BI dev " NAME " (default)
 the device name.
 
-.SS ip maddress add - add a multicast address
-.SS ip maddress delete - delete a multicast address
-these commands attach/detach a static link-layer multicast address
+.TP
+.B ip maddress add - add a multicast address
+.TP
+.B ip maddress delete - delete a multicast address
+.sp
+These commands attach/detach a static link-layer multicast address
 to listen on the interface.
 Note that it is impossible to join protocol multicast groups
 statically.  This command only manages link-layer addresses.
 
+.RS
 .TP
 .BI address " LLADDRESS " (default)
 the link-layer multicast address.
@@ -45,6 +49,7 @@
 .TP
 .BI dev " NAME"
 the device to join/leave this multicast address.
+.RE
 
 .SH SEE ALSO
 .br
diff --git a/man/man8/ip-neighbour.8 b/man/man8/ip-neighbour.8
index 5d9768f..67fbec7 100644
--- a/man/man8/ip-neighbour.8
+++ b/man/man8/ip-neighbour.8
@@ -46,10 +46,17 @@
 The corresponding commands display neighbour bindings
 and their properties, add new neighbour entries and delete old ones.
 
-.SS ip neighbour add - add a new neighbour entry
-.SS ip neighbour change - change an existing entry
-.SS ip neighbour replace - add a new entry or change an existing one
+.TP
+ip neighbour add
+add a new neighbour entry
+.TP
+ip neighbour change
+change an existing entry
+.TP
+ip neighbour replace
+add a new entry or change an existing one
 
+.PP
 These commands create new neighbour records or update existing ones.
 
 .TP
@@ -74,31 +81,28 @@
 is an abbreviation for 'Neighbour Unreachability Detection'.
 The state can take one of the following values:
 
-.in +8
+.TP
 .B permanent
-- the neighbour entry is valid forever and can be only
+the neighbour entry is valid forever and can be only
 be removed administratively.
-.sp
-
+.TP
 .B noarp
-- the neighbour entry is valid. No attempts to validate
+the neighbour entry is valid. No attempts to validate
 this entry will be made but it can be removed when its lifetime expires.
-.sp
-
+.TP
 .B reachable
-- the neighbour entry is valid until the reachability
+the neighbour entry is valid until the reachability
 timeout expires.
-.sp
-
+.TP
 .B stale
-- the neighbour entry is valid but suspicious.
+the neighbour entry is valid but suspicious.
 This option to
 .B ip neigh
 does not change the neighbour state if it was valid and the address
 is not changed by this command.
-.in -8
-
-.SS ip neighbour delete - delete a neighbour entry
+.RS
+ip neighbour delete - delete a neighbour entry
+.RE
 This command invalidates a neighbour entry.
 
 .PP
@@ -120,9 +124,11 @@
 .B NOARP
 interface or if the address is multicast or broadcast.
 
-.SS ip neighbour show - list neighbour entries
+.RS
+ip neighbour show - list neighbour entries
+.RE
 
-This commands displays neighbour tables.
+This command displays neighbour tables.
 
 .TP
 .BI to " ADDRESS " (default)
@@ -154,7 +160,10 @@
 and
 .BR "noarp" .
 
-.SS ip neighbour flush - flush neighbour entries
+.RS
+ip neighbour flush - flush neighbour entries
+.RE
+
 This command flushes neighbour tables, selecting
 entries to flush by some criteria.
 
diff --git a/man/man8/ip-netns.8 b/man/man8/ip-netns.8
index 87534be..6aa6e93 100644
--- a/man/man8/ip-netns.8
+++ b/man/man8/ip-netns.8
@@ -64,35 +64,41 @@
 bind mounting all of the per network namespace configure files into
 their traditional location in /etc.
 
-.SS ip netns list - show all of the named network namespaces
-
+.TP
+.B ip netns list - show all of the named network namespaces
+.sp
 This command displays all of the network namespaces in /var/run/netns
 
-.SS ip netns add NAME - create a new named network namespace
-
+.TP
+.B ip netns add NAME - create a new named network namespace
+.sp
 If NAME is available in /var/run/netns/ this command creates a new
 network namespace and assigns NAME.
 
-.SS ip netns delete NAME - delete the name of a network namespace
-
+.TP
+.B ip netns delete NAME - delete the name of a network namespace
+.sp
 If NAME is present in /var/run/netns it is umounted and the mount
 point is removed.  If this is the last user of the network namespace the
 network namespace will be freed, otherwise the network namespace
 persists until it has no more users.  ip netns delete may fail if
 the mount point is in use in another mount namespace.
 
-.SS ip netns identify PID - Report network namespaces names for process
-
+.TP
+.B ip netns identify PID - Report network namespaces names for process
+.sp
 This command walks through /var/run/netns and finds all the network
 namespace names for network namespace of the specified process.
 
-.SS ip netns pids NAME - Report processes in the named network namespace
-
+.TP
+.B ip netns pids NAME - Report processes in the named network namespace
+.sp
 This command walks through proc and finds all of the process who have
 the named network namespace as their primary network namespace.
 
-.SS ip netns exec NAME cmd ... - Run cmd in the named network namespace
-
+.TP
+.B ip netns exec NAME cmd ... - Run cmd in the named network namespace
+.sp
 This command allows applications that are network namespace unaware
 to be run in something other than the default network namespace with
 all of the configuration for the specified network namespace appearing
@@ -100,8 +106,9 @@
 are used to move files from their network namespace specific location
 to their default locations without affecting other processes.
 
-.SS ip netns monitor - Report as network namespace names are added and deleted
-
+.TP
+.B ip netns monitor - Report as network namespace names are added and deleted
+.sp
 This command watches network namespace name addition and deletion events
 and prints a line for each event it sees.
 
diff --git a/man/man8/ip-route.8.in b/man/man8/ip-route.8.in
index 01997fa..7191bce 100644
--- a/man/man8/ip-route.8.in
+++ b/man/man8/ip-route.8.in
@@ -248,10 +248,16 @@
 .I policy routing
 is used.
 
-.SS ip route add - add new route
-.SS ip route change - change route
-.SS ip route replace - change or add new one
-
+.TP
+ip route add
+add new route
+.TP
+ip route change
+change route
+.TP
+ip route replace
+change or add new one
+.RS
 .TP
 .BI to " TYPE PREFIX " (default)
 the destination prefix of the route.  If
@@ -508,9 +514,12 @@
 .B onlink
 pretend that the nexthop is directly attached to this link,
 even if it does not match any interface prefix.
+.RE
 
-.SS ip route delete - delete route
-
+.TP
+ip route delete
+delete route
+.RS
 .B ip route del
 has the same arguments as
 .BR "ip route add" ,
@@ -524,8 +533,12 @@
 If no route with the given key and attributes was found,
 .B ip route del
 fails.
+.RE
 
-.SS ip route show - list routes
+.TP
+ip route show
+list routes
+.RS
 the command displays the contents of the routing tables or the route(s)
 selected by some criteria.
 
@@ -634,8 +647,12 @@
 .TP
 .BI realms " FROMREALM/TOREALM"
 only list routes with these realms.
+.RE
 
-.SS ip route flush - flush routing tables
+.TP
+ip route flush
+flush routing tables
+.RS
 this command flushes routes selected by some criteria.
 
 .sp
@@ -658,8 +675,12 @@
 .B ip route flush
 also dumps all the deleted routes in the format described in the
 previous subsection.
+.RE
 
-.SS ip route get - get a single route
+.TP
+ip route get
+get a single route
+.RS
 this command gets a single route to a destination and prints its
 contents exactly as the kernel sees it.
 
@@ -713,21 +734,30 @@
 .B iif
 argument, the kernel pretends that a packet arrived from this interface
 and searches for a path to forward the packet.
+.RE
 
-.SS ip route save - save routing table information to stdout
-this command behaves like
+.TP
+ip route save
+save routing table information to stdout
+.RS
+This command behaves like
 .BR "ip route show"
 except that the output is raw data suitable for passing to
 .BR "ip route restore" .
+.RE
 
-.SS ip route restore - restore routing table information from stdin
-this command expects to read a data stream as returned from
+.TP
+ip route restore
+restore routing table information from stdin
+.RS
+This command expects to read a data stream as returned from
 .BR "ip route save" .
 It will attempt to restore the routing table information exactly as
 it was at the time of the save, so any translation of information
 in the stream (such as device indexes) must be done first.  Any existing
 routes are left unchanged.  Any routes specified in the data stream that
 already exist in the table will be ignored.
+.RE
 
 .SH EXAMPLES
 .PP
diff --git a/man/man8/ip-rule.8 b/man/man8/ip-rule.8
index 36f461b..36e46f1 100644
--- a/man/man8/ip-rule.8
+++ b/man/man8/ip-rule.8
@@ -140,7 +140,7 @@
 .sp
 The RPDB may contain rules of the following types:
 
-.in +8
+.RS
 .B unicast
 - the rule prescribes to return the route found
 in the routing table referenced by the rule.
@@ -158,11 +158,13 @@
 .B nat
 - the rule prescribes to translate the source address
 of the IP packet into some other value.
-.in -8
+.RE
 
-.SS ip rule add - insert a new rule
-.SS ip rule delete - delete a rule
-
+.TP
+.B ip rule add - insert a new rule
+.TP
+.B ip rule delete - delete a rule
+.RS
 .TP
 .BI type " TYPE " (default)
 the type of this rule.  The list of valid types was given in the previous
@@ -237,11 +239,12 @@
 immediately.  It is assumed that after a script finishes a batch of
 updates, it flushes the routing cache with
 .BR "ip route flush cache" .
-
-.SS ip rule flush - also dumps all the deleted rules.
+.RE
+.TP
+.B ip rule flush - also dumps all the deleted rules.
 This command has no arguments.
-
-.SS ip rule show - list rules
+.TP
+.B ip rule show - list rules
 This command has no arguments.
 The options list or lst are synonyms with show.
 
diff --git a/man/man8/ip-tunnel.8 b/man/man8/ip-tunnel.8
index cb05a4b..697e80d 100644
--- a/man/man8/ip-tunnel.8
+++ b/man/man8/ip-tunnel.8
@@ -88,10 +88,16 @@
 .B -f
 option.  The default is IPv4.
 
-.SS ip tunnel add - add a new tunnel
-.SS ip tunnel change - change an existing tunnel
-.SS ip tunnel delete - destroy a tunnel
-
+.TP
+.B ip tunnel add
+add a new tunnel
+.TP
+.B ip tunnel change
+change an existing tunnel
+.TP
+.B ip tunnel delete
+destroy a tunnel
+.RS
 .TP
 .BI name " NAME " (default)
 select the tunnel device name.
@@ -223,9 +229,12 @@
 .BI flowlabel " FLOWLABEL"
 .RB ( " only IPv6 tunnels " )
 set a fixed flowlabel.
+.RE
 
-.SS ip tunnel prl - potential router list (ISATAP only)
-
+.TP
+.B ip tunnel prl
+potential router list (ISATAP only)
+.RS
 .TP
 .BI dev " NAME"
 mandatory device name.
@@ -238,8 +247,11 @@
 .BI prl-delete " ADDR"
 .RB "Add or delete " ADDR
 as a potential router or default router.
+.RE
 
-.SS ip tunnel show - list tunnels
+.TP
+.B ip tunnel show
+list tunnels
 This command has no arguments.
 
 .SH SEE ALSO
diff --git a/man/man8/ip-xfrm.8 b/man/man8/ip-xfrm.8
index 1d33eed..2d31b4d 100644
--- a/man/man8/ip-xfrm.8
+++ b/man/man8/ip-xfrm.8
@@ -369,23 +369,19 @@
 object operating on the Security Policy Database). It is also used for
 the IP Payload Compression Protocol and features of Mobile IPv6.
 
-.SS ip xfrm state add - add new state into xfrm
-
-.SS ip xfrm state update - update existing state in xfrm
-
-.SS ip xfrm state allocspi - allocate an SPI value
-
-.SS ip xfrm state delete - delete existing state in xfrm
-
-.SS ip xfrm state get - get existing state in xfrm
-
-.SS ip xfrm state deleteall - delete all existing state in xfrm
-
-.SS ip xfrm state list - print out the list of existing state in xfrm
-
-.SS ip xfrm state flush - flush all state in xfrm
-
-.SS ip xfrm state count - count all existing state in xfrm
+.TS
+l l.
+ip xfrm state add	add new state into xfrm
+ip xfrm state update	update existing state in xfrm
+ip xfrm state allocspi	allocate an SPI value
+ip xfrm state delete	delete existing state in xfrm
+ip xfrm state get	get existing state in xfrm
+ip xfrm state deleteall	delete all existing state in xfrm
+ip xfrm state list	print out the list of existing state in xfrm
+ip xfrm state flush	flush all state in xfrm
+ip xfrm state count	count all existing state in xfrm
+ip xfrm monitor 	state monitoring for xfrm objects
+.TE
 
 .TP
 .IR ID
@@ -506,22 +502,18 @@
 .BR espinudp " or " espinudp-nonike ","
 .RI "using source port " SPORT ", destination port "  DPORT
 .RI ", and original address " OADDR "."
-
-.SS ip xfrm policy add - add a new policy
-
-.SS ip xfrm policy update - update an existing policy
-
-.SS ip xfrm policy delete - delete an existing policy
-
-.SS ip xfrm policy get - get an existing policy
-
-.SS ip xfrm policy deleteall - delete all existing xfrm policies
-
-.SS ip xfrm policy list - print out the list of xfrm policies
-
-.SS ip xfrm policy flush - flush policies
-
-.SS ip xfrm policy count - count existing policies
+.sp
+.TS
+l l.
+ip xfrm policy add	add a new policy
+ip xfrm policy update	update an existing policy
+ip xfrm policy delete	delete an existing policy
+ip xfrm policy get	get an existing policy
+ip xfrm policy deleteall	delete all existing xfrm policies
+ip xfrm policy list	print out the list of xfrm policies
+ip xfrm policy flush	flush policies
+ip xfrm policy count	count existing policies
+.TE
 
 .TP
 .IR SELECTOR
@@ -615,7 +607,6 @@
 can be
 .BR required " (default) or " use "."
 
-.SS ip xfrm monitor - state monitoring for xfrm objects
 The xfrm objects to monitor can be optionally specified.
 
 .SH AUTHOR
diff --git a/man/man8/ip.8 b/man/man8/ip.8
index 37f9988..9065b3a 100644
--- a/man/man8/ip.8
+++ b/man/man8/ip.8
@@ -12,6 +12,12 @@
 .sp
 
 .ti -8
+.B ip 
+.RB "[ " -force " ] "
+.BI "-batch " filename
+.sp
+
+.ti -8
 .IR OBJECT " := { "
 .BR link " | " addr " | " addrlabel " | " route " | " rule " | " neigh " | "\
  ntable " | " tunnel " | " tuntap " | " maddr " | "  mroute " | " mrule " | "\
@@ -27,17 +33,28 @@
 .BR inet " | " inet6 " | " ipx " | " dnet " | " link " } | "
 \fB\-o\fR[\fIneline\fR] }
 
+
 .SH OPTIONS
 
 .TP
 .BR "\-V" , " -Version"
-print the version of the
+Print the version of the
 .B ip
 utility and exit.
 
 .TP
+.BR "\-b", " \-batch " <FILENAME>
+Read commands from provided file or standard input and invoke them.
+First failure will cause termination of ip.
+
+.TP
+.BR "\-force"
+Don't terminate ip on errors in batch mode.
+If there were any errors during execution of the commands, the application return code will be non zero.
+
+.TP
 .BR "\-s" , " \-stats" , " \-statistics"
-output more information.  If the option
+Output more information.  If the option
 appears twice or more, the amount of information increases.
 As a rule, the information is statistics or some time values.
 
diff --git a/man/man8/tc-ematch.8 b/man/man8/tc-ematch.8
index 567ce7d..b9bf70c 100644
--- a/man/man8/tc-ematch.8
+++ b/man/man8/tc-ematch.8
@@ -6,54 +6,43 @@
 .SH SYNOPSIS
 .sp
 .ad l
-.in +8
-.ti -8
 .B "tc filter add .. basic match"
 .RI EXPR
 .B .. flowid ..
 .sp
 
-.ti -8
 .IR EXPR " := " TERM " [ { "
 .B and | or
 }
 .IR EXPR
 ]
 
-.ti -8
 .IR TERM " := [ " \fBnot " ] { " MATCH " | '(' " EXPR " ')' } "
 
-.ti -8
 .IR MATCH " := " module " '(' " ARGS " ')' "
 
-.ti -8
 .IR ARGS " := " ARG1 " " ARG2 " ..
 
 .SH MATCHES
 
 .SS cmp
 Simple comparison ematch: arithmetic compare of packet data to a given value.
-.ti
+
 .IR cmp "( " ALIGN " at " OFFSET " [ " ATTRS " ] { " eq " | " lt " | " gt " } " VALUE " )
 
-.ti
 .IR ALIGN " := { " u8 " | " u16 " | " u32 " } "
 
-.ti
 .IR ATTRS " := [ layer " LAYER " ] [ mask " MASK " ] [ trans ]
 
-.ti
 .IR LAYER " := { " link " | " network " | " transport " | " 0..2 " }
 
 .SS meta
 Metadata ematch
-.ti
+
 .IR meta "( " OBJECT " { " eq " | " lt " |" gt " } " OBJECT " )
 
-.ti
 .IR OBJECT " := { " META_ID " |  " VALUE " }
 
-.ti
 .IR META_ID " := " id " [ shift " SHIFT " ] [ mask " MASK " ]
 
 .TP
@@ -78,35 +67,29 @@
 
 .SS nbyte
 match packet data byte sequence
-.ti
+
 .IR nbyte "( " NEEDLE  " at " OFFSET " [ layer " LAYER " ] )
 
-.ti
 .IR NEEDLE  " := { " string " | " c-escape-sequence "  } "
 
-.ti
 .IR OFFSET  " := " int
 
-.ti
 .IR LAYER " := { " link " | " network " | " transport " | " 0..2 " }
 
 .SS u32
 u32 ematch
-.ti
+
 .IR u32 "( " ALIGN " " VALUE " " MASK " at [ nexthdr+ ] " OFFSET " )
 
-.ti
 .IR ALIGN " := { " u8 " | " u16 " | " u32 " }
 
 .SS ipset
 test packet against ipset membership
-.ti
+
 .IR ipset "( " SETNAME " " FLAGS " )
 
-.ti
 .IR SETNAME " := " string
 
-.ti
 .IR FLAGS " := { " FLAG " [, " FLAGS "] }
 
 The flag options are the same as those used by the iptables "set" match.
diff --git a/man/man8/tc-stab.8 b/man/man8/tc-stab.8
index 522ea00..02caa7d 100644
--- a/man/man8/tc-stab.8
+++ b/man/man8/tc-stab.8
@@ -5,15 +5,15 @@
 .
 .SH SYNOPSIS
 .nf
-tc qdisc add ... stab \\
+tc qdisc add ... stab
 .RS 4
-[ \fBmtu\fR BYTES ] [ \fBtsize\fR SLOTS ] \\
-[ \fBmpu\fR BYTES ] [ \fBoverhead\fR BYTES ] [ \fBlinklayer\fR TYPE ] ...
+[ \fBmtu\fR BYTES ] [ \fBtsize\fR SLOTS ]
+[ \fBmpu\fR BYTES ] [ \fBoverhead\fR BYTES ]
+[ \fBlinklayer\fR { adsl | atm | ethernet } ] ...
 .RE
-
-TYPE := adsl | atm | ethernet
 .fi
 
+.SH OPTIONS
 For the description of BYTES \- please refer to the \fBUNITS\fR
 section of \fBtc\fR(8).
 
@@ -31,27 +31,27 @@
 per\-packet size overhead (can be negative) used in computations
 .IP \fBlinklayer\fR
 .br
-required linklayer adaptation.
+required linklayer specification.
 .PP
 .
 .SH DESCRIPTION
 .
-Size tables allow manipulation of packet size, as seen by whole scheduler
+Size tables allow manipulation of packet sizes, as seen by the whole scheduler
 framework (of course, the actual packet size remains the same). Adjusted packet
 size is calculated only once \- when a qdisc enqueues the packet. Initial root
 enqueue initializes it to the real packet's size.
 
-Each qdisc can use different size table, but the adjusted size is stored in
-area shared by whole qdisc hierarchy attached to the interface. The effect is,
-that if you have such setup, the last qdisc with a stab in a chain "wins". For
+Each qdisc can use a different size table, but the adjusted size is stored in
+an area shared by whole qdisc hierarchy attached to the interface. The effect is
+that if you have such a setup, the last qdisc with a stab in a chain "wins". For
 example, consider HFSC with simple pfifo attached to one of its leaf classes.
 If that pfifo qdisc has stab defined, it will override lengths calculated
-during HFSC's enqueue, and in turn, whenever HFSC tries to dequeue a packet, it
-will use potentially invalid size in its calculations. Normal setups will
+during HFSC's enqueue; and in turn, whenever HFSC tries to dequeue a packet, it
+will use a potentially invalid size in its calculations. Normal setups will
 usually include stab defined only on root qdisc, but further overriding gives
 extra flexibility for less usual setups.
 
-Initial size table is calculated by \fBtc\fR tool using \fBmtu\fR and
+The initial size table is calculated by \fBtc\fR tool using \fBmtu\fR and
 \fBtsize\fR parameters. The algorithm sets each slot's size to the smallest
 power of 2 value, so the whole \fBmtu\fR is covered by the size table. Neither
 \fBtsize\fR, nor \fBmtu\fR have to be power of 2 value, so the size
@@ -65,12 +65,12 @@
 Stab calculation is also safe for an unusual case, when a size assigned to a
 slot would be larger than 2^16\-1 (you will lose the accuracy though).
 
-During kernel part of packet size adjustment, \fBoverhead\fR will be added to
-original size, and then slot will be calculated. If the size would cause
-overflow, more than 1 slot will be used to get the final size. It of course
+During the kernel part of packet size adjustment, \fBoverhead\fR will be added
+to original size, and then slot will be calculated. If the size would cause
+overflow, more than 1 slot will be used to get the final size. This of course
 will affect accuracy, but it's only a guard against unusual situations.
 
-Currently there're two methods of creating values stored in the size table \-
+Currently there are two methods of creating values stored in the size table \-
 ethernet and atm (adsl):
 
 .IP ethernet 4
@@ -78,7 +78,7 @@
 This is basically 1\-1 mapping, so following our example from above
 (disregarding \fBmpu\fR for a moment) slot 0 would have 8, slot 1 would have 16
 and so on, up to slot 127 with 2048. Note, that \fBmpu\fR\~>\~0 must be
-specified, and slots that would get less than specified by \fBmpu\fR, will get
+specified, and slots that would get less than specified by \fBmpu\fR will get
 \fBmpu\fR instead. If you don't specify \fBmpu\fR, the size table will not be
 created at all (it wouldn't make any difference), although any \fBoverhead\fR
 value will be respected during calculations.
@@ -88,7 +88,7 @@
 for payload. Also all the cells must be fully utilized, thus the last one is
 padded if/as necessary.
 
-When size table is calculated, adjusted size that fits properly into lowest
+When the size table is calculated, adjusted size that fits properly into lowest
 amount of cells is assigned to a slot. For example, a 100 byte long packet
 requires three 48\-byte payloads, so the final size would require 3 ATM cells
 \- 159 bytes.
@@ -118,22 +118,22 @@
 IPoA \- 8 (ATM \- 8)
 .RE
 .fi
-\p There're few important things regarding the above overheads:
+There are a few important things regarding the above overheads:
 .
 .IP \(bu 4
 IPoA in LLC case requires SNAP, instead of LLC\-NLPID (see rfc2684) \- this is
-the reason, why it actually takes more space than PPPoA.
+the reason why it actually takes more space than PPPoA.
 .IP \(bu
-In rare cases, FCS might be preserved on protocols that include ethernet frame
-(Bridged and PPPoE). In such situation, any ethernet specific padding
-guaranteeing 64 bytes long frame size has to be included as well (see rfc2684).
+In rare cases, FCS might be preserved on protocols that include Ethernet frames
+(Bridged and PPPoE). In such situation, any Ethernet specific padding
+guaranteeing 64 bytes long frame size has to be included as well (see RFC2684).
 In the other words, it also guarantees that any packet you send will take
 minimum 2 atm cells. You should set \fBmpu\fR accordingly for that.
 .IP \(bu
-When size table is consulted, and you're shaping traffic for the sake of
-another modem/router, ethernet header (without padding) will already be added
+When the size table is consulted, and you're shaping traffic for the sake of
+another modem/router, an Ethernet header (without padding) will already be added
 to initial packet's length. You should compensate for that by subtracting 14
-from the above overheads in such case. If you're shaping directly on the router
+from the above overheads in this case. If you're shaping directly on the router
 (for example, with speedtouch usb modem) using ppp daemon, you're using raw ip
 interface without underlying layer2, so nothing will be added.
 
@@ -141,10 +141,10 @@
 .
 .SH "ETHERNET CARDS CONSIDERATIONS"
 .
-It's often forgotten, that modern network cards (even cheap ones on desktop
+It's often forgotten that modern network cards (even cheap ones on desktop
 motherboards) and/or their drivers often support different offloading
-mechanisms. In context of traffic shaping, 'tso' and 'gso' might cause
-undesirable effects, due to massive tcp segments being considered during
+mechanisms. In the context of traffic shaping, 'tso' and 'gso' might cause
+undesirable effects, due to massive TCP segments being considered during
 traffic shaping (including stab calculations). For slow uplink interfaces,
 it's good to use \fBethtool\fR to turn off offloading features.
 .
diff --git a/misc/ss.c b/misc/ss.c
index e0d11ff..c0369f1 100644
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -1435,6 +1435,19 @@
 					 / rtt));
 		}
 
+		if (info->tcpi_unacked)
+			printf(" unacked:%u", info->tcpi_unacked);
+		if (info->tcpi_retrans || info->tcpi_total_retrans)
+			printf(" retrans:%u/%u", info->tcpi_retrans,
+			       info->tcpi_total_retrans);
+		if (info->tcpi_lost)
+			printf(" lost:%u", info->tcpi_lost);
+		if (info->tcpi_sacked && r->idiag_state != SS_LISTEN)
+			printf(" sacked:%u", info->tcpi_sacked);
+		if (info->tcpi_fackets)
+			printf(" fackets:%u", info->tcpi_fackets);
+		if (info->tcpi_reordering != 3)
+			printf(" reordering:%d", info->tcpi_reordering);
 		if (info->tcpi_rcv_rtt)
 			printf(" rcv_rtt:%g", (double) info->tcpi_rcv_rtt/1000);
 		if (info->tcpi_rcv_space)
diff --git a/tc/tc.c b/tc/tc.c
index 8e362d2..9b50e74 100644
--- a/tc/tc.c
+++ b/tc/tc.c
@@ -34,6 +34,7 @@
 int show_details = 0;
 int show_raw = 0;
 int show_pretty = 0;
+int batch_mode = 0;
 
 int resolve_hosts = 0;
 int use_iec = 0;
@@ -220,6 +221,7 @@
 	size_t len = 0;
 	int ret = 0;
 
+	batch_mode = 1;
 	if (name && strcmp(name, "-") != 0) {
 		if (freopen(name, "r", stdin) == NULL) {
 			fprintf(stderr, "Cannot open file \"%s\" for reading: %s\n",
@@ -262,8 +264,7 @@
 int main(int argc, char **argv)
 {
 	int ret;
-	int do_batching = 0;
-	char *batchfile = NULL;
+	char *batch_file = NULL;
 
 	while (argc > 1) {
 		if (argv[1][0] != '-')
@@ -288,10 +289,10 @@
 		} else if (matches(argv[1], "-force") == 0) {
 			++force;
 		} else 	if (matches(argv[1], "-batch") == 0) {
-			do_batching = 1;
-			if (argc > 2)
-				batchfile = argv[2];
 			argc--;	argv++;
+			if (argc <= 1)
+				usage();
+			batch_file = argv[1];
 		} else {
 			fprintf(stderr, "Option \"%s\" is unknown, try \"tc -help\".\n", argv[1]);
 			return -1;
@@ -299,8 +300,8 @@
 		argc--;	argv++;
 	}
 
-	if (do_batching)
-		return batch(batchfile);
+	if (batch_file)
+		return batch(batch_file);
 
 	if (argc <= 1) {
 		usage();