On 11/27/2012 09:36 AM, Neil Carter wrote:
Greetings:

I've checked the debug files and bsdtcp is what's actually being used.

Yes, there are four NICs on the Amanda server and generally one on each client. Yes, they are ALL on the same subnet.

So, you're suggesting I need to create a route for each server in the routing table? If that's the case, then what's the purpose of the interface directive in the disklist file? It would seem redundant.
It is just for amanda to manage the bandwidth.

Try the attached patch, it add a "src-ip" in the interface section, the NIC with that IP should be used.

define interface lo0 {
    src-ip "127.0.0.1"
}

All dles for one host must use the same interface.

Jean-Louis

Thanks!

Neil


On 2012.11.27 6:19 AM, Jean-Louis Martineau wrote:
On 11/26/2012 06:50 PM, Neil Carter wrote:
Greetings:

It's using the BSDTCPAuth(?), the default in 3.3.0, I think.
It is the default, is it what you are using? Check your amandad.*.debug files on the client, you will see it in uppercase.


The issue isn't in contacting the client servers from the Amanda server, it's how to get the huge amounts of data back from the client to the server.

With bsdtcp, the data should come back from the same interface the request goes out.

If I understand, your server have for NIC and four IP, your client have one NIC and one IP? all of them on the same subnet? Try adding a route on the server so that request to the client goes out from the IP you want.

Jean-Louis



Thanks!

Neil


On 2012.11.26 5:17 PM, Jean-Louis Martineau wrote:
Neil,

Amanda resolve the hostname from the disklist to get an IP and send packet to that IP.
You can add network route to route some IP to some interface.

Which auth are you using?

Jean-Louis


On 11/26/2012 04:34 PM, Neil Carter wrote:
Greetings:

Yes, I've looked into this, the network engineer (separate group) is not interested in bonding, so that won't work. I have to use the four NICs as independent interfaces.

Also, a few more information tidbits:

1.  All servers are on the same subnet
2. NIS is used to push the hosts file out to all of the servers (I'd played with having a separate hosts listing for each NIC, then modifying the password-less ssh to get things to work - no luck).

I'm assuming the client is just sending the data to the server hostname via the hosts file, so I'd like to find more detail on how to use the disklist interface directive, I think. It appears the amandahosts file has more to do with authentication than actually working like a hosts file.

Thanks!

Neil



On Mon, Nov 26, 2012 at 2:46 PM, Dennis Benndorf <[email protected] <mailto:[email protected]>> wrote:

    Hello Neil,

    thats not a thing of amanda, instead it is a thing of the
    operation system. If you are using a linux distributionen you
    should google "bonding". In order to have the full bandwith the
    ports at the switch have to be configured to act as one.

    Regards,
    Dennis



    Am 26.11.2012 21:27, schrieb Neil Carter:

        Greetings:

        My Amanda 3.3.0 server has four gigabit NICs that I'd like to
        make full use of in performing the backups.  It's currently
        running (for almost a year now) on only one NIC.

        In the disklist file, I can add the interface directive eth0,
        eth1, eth2, or eth3.  I've done that, round-robin, to the
        numerous entries.  However, all traffic continues to come
        through eth0. All four interfaces have properly configured,
        and functioning, IP addresses.

        Is this something so simple as to change the entry in the
        .amandahosts file?

        Anybody have experience with this?

        Thanks!

        Neil










diff --git a/client-src/sendbackup.c b/client-src/sendbackup.c
index 71f017e..1cf3818 100644
--- a/client-src/sendbackup.c
+++ b/client-src/sendbackup.c
@@ -608,7 +608,7 @@ main(
 		str_port = strchr(indirect_tcp, ':');
 		str_port++;
 		port = atoi(str_port);
-		fd = stream_client("localhost", port, 32768, 32768, NULL, 0);
+		fd = stream_client(NULL, "localhost", port, 32768, 32768, NULL, 0);
 		if (fd <= 0) {
 		    g_debug("Failed to connect to indirect-direct-tcp port: %s",
 			    strerror(errno));
diff --git a/common-src/bsd-security.c b/common-src/bsd-security.c
index 82348ed..4a253ae 100644
--- a/common-src/bsd-security.c
+++ b/common-src/bsd-security.c
@@ -460,7 +460,7 @@ bsd_stream_client(
 
     bs = g_new0(struct sec_stream, 1);
     security_streaminit(&bs->secstr, &bsd_security_driver);
-    bs->fd = stream_client(bh->hostname, (in_port_t)id,
+    bs->fd = stream_client(NULL, bh->hostname, (in_port_t)id,
 	STREAM_BUFSIZE, STREAM_BUFSIZE, &bs->port, 0);
     if (bs->fd < 0) {
 	security_seterror(&bh->sech,
diff --git a/common-src/bsdtcp-security.c b/common-src/bsdtcp-security.c
index 25a32ac..28ea57c 100644
--- a/common-src/bsdtcp-security.c
+++ b/common-src/bsdtcp-security.c
@@ -91,7 +91,7 @@ static int newhandle = 1;
 /*
  * Local functions
  */
-static int runbsdtcp(struct sec_handle *, in_port_t port);
+static int runbsdtcp(struct sec_handle *, const char *src_ip, in_port_t port);
 
 
 /*
@@ -110,6 +110,7 @@ bsdtcp_connect(
     int result;
     char *canonname;
     char *service;
+    char *src_ip;
     in_port_t port;
 
     assert(fn != NULL);
@@ -158,8 +159,10 @@ bsdtcp_connect(
 	service = conf_fn("client_port", datap);
 	if (!service || strlen(service) <= 1)
 	    service = "amanda";
+	src_ip = conf_fn("src_ip", datap);
     } else {
 	service = "amanda";
+	src_ip = NULL;
     }
     port = find_port_for_service(service, "tcp");
     if (port == 0) {
@@ -173,7 +176,7 @@ bsdtcp_connect(
      * XXX need to eventually limit number of outgoing connections here.
      */
     if(rh->rc->read == -1) {
-	if (runbsdtcp(rh, port) < 0)
+	if (runbsdtcp(rh, src_ip, port) < 0)
 	    goto error;
 	rh->rc->refcnt++;
     }
@@ -255,6 +258,7 @@ bsdtcp_accept(
 static int
 runbsdtcp(
     struct sec_handle *	rh,
+    const char *src_ip,
     in_port_t port)
 {
     int			server_socket;
@@ -263,7 +267,8 @@ runbsdtcp(
 
     set_root_privs(1);
 
-    server_socket = stream_client_privileged(rc->hostname,
+    server_socket = stream_client_privileged(src_ip,
+				     rc->hostname,
 				     port,
 				     STREAM_BUFSIZE,
 				     STREAM_BUFSIZE,
diff --git a/common-src/conffile.c b/common-src/conffile.c
index ae50db9..247850e 100644
--- a/common-src/conffile.c
+++ b/common-src/conffile.c
@@ -156,6 +156,7 @@ typedef enum {
 
     /* network interface */
     /* COMMENT, */		/* USE, */
+    CONF_SRC_IP,
 
     /* dump options (obsolete) */
     CONF_EXCLUDE_FILE,		CONF_EXCLUDE_LIST,
@@ -1081,6 +1082,7 @@ keytab_t server_keytab[] = {
     { "SMALLEST", CONF_SMALLEST },
     { "SPEED", CONF_SPEED },
     { "SPLIT_DISKBUFFER", CONF_SPLIT_DISKBUFFER },
+    { "SRC_IP", CONF_SRC_IP },
     { "SSH_KEYS", CONF_SSH_KEYS },
     { "STANDARD", CONF_STANDARD },
     { "STARTTIME", CONF_STARTTIME },
@@ -1405,6 +1407,7 @@ conf_var_t holding_var [] = {
 conf_var_t interface_var [] = {
    { CONF_COMMENT, CONFTYPE_STR   , read_str   , INTER_COMMENT , NULL },
    { CONF_USE    , CONFTYPE_INT   , read_int   , INTER_MAXUSAGE, validate_positive },
+   { CONF_SRC_IP , CONFTYPE_STR   , read_str   , INTER_SRC_IP  , NULL },
    { CONF_UNKNOWN, CONFTYPE_INT   , NULL       , INTER_INTER   , NULL }
 };
 
@@ -2622,7 +2625,8 @@ static void
 init_interface_defaults(void)
 {
     conf_init_str(&ifcur.value[INTER_COMMENT] , "");
-    conf_init_int   (&ifcur.value[INTER_MAXUSAGE], CONF_UNIT_K, 80000);
+    conf_init_int(&ifcur.value[INTER_MAXUSAGE], CONF_UNIT_K, 80000);
+    conf_init_str(&ifcur.value[INTER_SRC_IP], "NULL");
 }
 
 static void
diff --git a/common-src/conffile.h b/common-src/conffile.h
index efb7253..53f3f87 100644
--- a/common-src/conffile.h
+++ b/common-src/conffile.h
@@ -828,6 +828,7 @@ char *dumptype_name(dumptype_t *dtyp);
 typedef enum {
     INTER_COMMENT,
     INTER_MAXUSAGE,
+    INTER_SRC_IP,
     INTER_INTER /* sentinel */
 } interface_key;
 
@@ -873,6 +874,7 @@ char *interface_name(interface_t *iface);
  */
 #define interface_get_comment(iface)    (val_t_to_str(interface_getconf((iface), INTER_COMMENT)))
 #define interface_get_maxusage(iface)   (val_t_to_int(interface_getconf((iface), INTER_MAXUSAGE)))
+#define interface_get_src_ip(iface)     (val_t_to_str(interface_getconf((iface), INTER_SRC_IP)))
 
 /*
  * Holdingdisk parameter access
diff --git a/common-src/security-util.c b/common-src/security-util.c
index cda59ba..83b894f 100644
--- a/common-src/security-util.c
+++ b/common-src/security-util.c
@@ -870,7 +870,7 @@ tcp1_stream_client(
 	rh->rc = sec_tcp_conn_get(rh->hostname, 1);
 	rh->rc->driver = rh->sech.driver;
 	rs->rc = rh->rc;
-	rh->rc->read = stream_client(rh->hostname, (in_port_t)id,
+	rh->rc->read = stream_client(NULL, rh->hostname, (in_port_t)id,
 			STREAM_BUFSIZE, STREAM_BUFSIZE, &rs->port, 0);
 	if (rh->rc->read < 0) {
 	    security_seterror(&rh->sech,
diff --git a/common-src/sockaddr-util.h b/common-src/sockaddr-util.h
index d9cf647..2094f57 100644
--- a/common-src/sockaddr-util.h
+++ b/common-src/sockaddr-util.h
@@ -138,6 +138,29 @@ int	str_to_sockaddr(
 } while (0);
 #endif
 
+/* Set the IP in a sockaddr_union that already has an family
+ *
+ * @param su: the sockaddr_union to manipulate
+ * @param ip: the IP to insert
+ */
+/* SU_SET_INADDR(su, ip) */
+#ifdef WORKING_IPV6
+#define SU_SET_INADDR(su, ip) do { \
+    switch (SU_GET_FAMILY(su)) { \
+	case AF_INET6: \
+            (su)->sin6.sin6_flowinfo = 0; \
+	    inet_pton(SU_GET_FAMILY(su), ip, &((su)->sin6.sin6_addr)); \
+	    break; \
+	case AF_INET: \
+	    inet_pton(SU_GET_FAMILY(su), ip, &((su)->sin.sin_addr)); \
+	    break; \
+    } \
+} while (0);
+#else
+#define SU_SET_INADDR(su, ip) \
+    inet_pton(SU_GET_FAMILY(su), ip, &((su)->sin.sin_addr));
+#endif
+
 /* Set the port in a sockaddr_union that already has an family
  *
  * @param su: the sockaddr_union to manipulate
diff --git a/common-src/stream.c b/common-src/stream.c
index e45d27d..8be35e4 100644
--- a/common-src/stream.c
+++ b/common-src/stream.c
@@ -40,7 +40,8 @@
 
 /* local functions */
 static void try_socksize(int sock, int which, size_t size);
-static int stream_client_internal(const char *hostname, in_port_t port,
+static int stream_client_internal(const char *src_ip,
+		const char *hostname, in_port_t port,
 		size_t sendsize, size_t recvsize, in_port_t *localport,
 		int nonblock, int priv);
 
@@ -196,6 +197,7 @@ out:
 
 static int
 stream_client_internal(
+    const char *src_ip,
     const char *hostname,
     in_port_t port,
     size_t sendsize,
@@ -230,6 +232,9 @@ stream_client_internal(
 
 	SU_INIT(&claddr, SU_GET_FAMILY(&svaddr));
 	SU_SET_INADDR_ANY(&claddr);
+	if (src_ip) {
+	    SU_SET_INADDR(&claddr, src_ip);
+	}
 
 	/*
 	 * If a privileged port range was requested, we try to get a port in
@@ -275,6 +280,7 @@ out:
 
 int
 stream_client_privileged(
+    const char *src_ip,
     const char *hostname,
     in_port_t port,
     size_t sendsize,
@@ -282,7 +288,8 @@ stream_client_privileged(
     in_port_t *localport,
     int nonblock)
 {
-    return stream_client_internal(hostname,
+    return stream_client_internal(src_ip,
+				  hostname,
 				  port,
 				  sendsize,
 				  recvsize,
@@ -293,6 +300,7 @@ stream_client_privileged(
 
 int
 stream_client(
+    const char *src_ip,
     const char *hostname,
     in_port_t port,
     size_t sendsize,
@@ -300,7 +308,8 @@ stream_client(
     in_port_t *localport,
     int nonblock)
 {
-    return stream_client_internal(hostname,
+    return stream_client_internal(src_ip,
+				  hostname,
 				  port,
 				  sendsize,
 				  recvsize,
diff --git a/common-src/stream.h b/common-src/stream.h
index ed8f006..8edfca6 100644
--- a/common-src/stream.h
+++ b/common-src/stream.h
@@ -41,13 +41,15 @@
 int stream_server(int family, in_port_t *port, size_t sendsize,
 		  size_t recvsize, int priv);
 int stream_accept(int sock, int timeout, size_t sendsize, size_t recvsize);
-int stream_client_privileged(const char *hostname,
+int stream_client_privileged(const char *src_ip,
+				const char *hostname,
 				in_port_t port,
 				size_t sendsize,
 				size_t recvsize,
 				in_port_t *localport,
 				int nonblock);
-int stream_client(const char *hostname,
+int stream_client(const char *src_ip,
+		     const char *hostname,
 		     in_port_t port,
 		     size_t sendsize,
 		     size_t recvsize,
diff --git a/oldrecover-src/amrecover.c b/oldrecover-src/amrecover.c
index 39bc3c2..8ba9f93 100644
--- a/oldrecover-src/amrecover.c
+++ b/oldrecover-src/amrecover.c
@@ -541,7 +541,8 @@ main(
 	/*NOTREACHED*/
     }
     amfree(service_name);
-    server_socket = stream_client_privileged(server_name,
+    server_socket = stream_client_privileged(NULL,
+					     server_name,
 					     (in_port_t)ntohs((in_port_t)sp->s_port),
 					     0,
 					     0,
diff --git a/oldrecover-src/extract_list.c b/oldrecover-src/extract_list.c
index 43971d7..cd27bf2 100644
--- a/oldrecover-src/extract_list.c
+++ b/oldrecover-src/extract_list.c
@@ -1338,7 +1338,8 @@ extract_files_setup(
     amfree(service_name);
     seteuid(0);					/* it either works ... */
     setegid(0);
-    tape_control_sock = stream_client_privileged(tape_server_name,
+    tape_control_sock = stream_client_privileged(NULL,
+						  tape_server_name,
 						  (in_port_t)ntohs((in_port_t)sp->s_port),
 						  0,
 						  STREAM_BUFSIZE,
@@ -1520,7 +1521,8 @@ extract_files_setup(
 	    /*NOTREACHED*/
         }	
 
-	tape_data_sock = stream_client_privileged(server_name,
+	tape_data_sock = stream_client_privileged(NULL,
+						  server_name,
 						  data_port,
 						  0,
 						  STREAM_BUFSIZE,
diff --git a/server-src/driverio.c b/server-src/driverio.c
index 8e41646..97d8883 100644
--- a/server-src/driverio.c
+++ b/server-src/driverio.c
@@ -653,6 +653,7 @@ dumper_cmd(
 	    cmdline = vstralloc(cmdstr[cmd],
 			    " ", disk2serial(dp),
 			    " ", numberport,
+			    " ", interface_get_src_ip(dp->host->netif->config),
 			    " ", dp->host->hostname,
 			    " ", features,
 			    " ", qname,
diff --git a/server-src/dumper.c b/server-src/dumper.c
index 1c75398..5adcfbb 100644
--- a/server-src/dumper.c
+++ b/server-src/dumper.c
@@ -104,6 +104,7 @@ char *clnt_decrypt_opt = NULL;
 static kencrypt_type dumper_kencrypt;
 
 static FILE *errf = NULL;
+static char *src_ip = NULL;
 static char *hostname = NULL;
 am_feature_t *their_features = NULL;
 static char *diskname = NULL;
@@ -423,6 +424,7 @@ main(
 	     * PORT-DUMP
 	     *   handle
 	     *   port
+	     *   src_ip
 	     *   host
 	     *   features
 	     *   disk
@@ -454,6 +456,13 @@ main(
 	    header_port = (in_port_t)atoi(cmdargs->argv[a++]);
 
 	    if(a >= cmdargs->argc) {
+		error(_("error [dumper PORT-DUMP: not enough args: src_ip]"));
+		/*NOTREACHED*/
+	    }
+	    g_free(src_ip);
+	    src_ip = g_strdup(cmdargs->argv[a++]);
+
+	    if(a >= cmdargs->argc) {
 		error(_("error [dumper PORT-DUMP: not enough args: hostname]"));
 		/*NOTREACHED*/
 	    }
@@ -571,7 +580,7 @@ main(
 	    /* connect outf to chunker/taper port */
 
 	    g_debug(_("Sending header to localhost:%d\n"), header_port);
-	    outfd = stream_client("localhost", header_port,
+	    outfd = stream_client(NULL, "localhost", header_port,
 				  STREAM_BUFSIZE, 0, NULL, 0);
 	    if (outfd == -1) {
 		
@@ -1596,7 +1605,7 @@ read_mesgfd(
 	aclose(db->fd);
 	if (data_path == DATA_PATH_AMANDA) {
 	    g_debug(_("Sending data to %s:%d\n"), data_host, data_port);
-	    db->fd = stream_client(data_host, data_port,
+	    db->fd = stream_client(NULL, data_host, data_port,
 				   STREAM_BUFSIZE, 0, NULL, 0);
 	    if (db->fd == -1) {
 		errstr = newvstrallocf(errstr,
@@ -2335,6 +2344,11 @@ dumper_get_security_conf(
                 return (client_username);
         } else if(strcmp(string, "client_port")==0) {
                 return (client_port);
+        } else if(strcmp(string, "src_ip")==0) {
+		if (g_str_equal(src_ip, "NULL"))
+		    return NULL;
+		else
+		    return (src_ip);
         } else if(strcmp(string, "ssh_keys")==0) {
                 return (ssh_keys);
         } else if(strcmp(string, "kencrypt")==0) {
diff --git a/server-src/server_util.c b/server-src/server_util.c
index 72462a3..46399f1 100644
--- a/server-src/server_util.c
+++ b/server-src/server_util.c
@@ -158,7 +158,13 @@ amhost_get_security_conf(
 	return ((am_host_t *)arg)->disks->client_username;
     else if(strcmp(string, "client_port")==0)
 	return ((am_host_t *)arg)->disks->client_port;
-    else if(strcmp(string, "ssh_keys")==0)
+    else if(g_str_equal(string, "src_ip")) {
+	char *src_ip = interface_get_src_ip(((am_host_t *)arg)->netif->config);
+	if (g_str_equal(src_ip, "NULL"))
+	    return NULL;
+	else
+	    return src_ip;
+    } else if(strcmp(string, "ssh_keys")==0)
 	return ((am_host_t *)arg)->disks->ssh_keys;
 
     return(NULL);

Reply via email to