mirror of
https://github.com/openvswitch/ovs
synced 2025-08-24 02:47:14 +00:00
On Windows platform, TCP_NODELAY can only be set when TCP is established. (This is an observed behavior and not written in any MSDN documentation.) The current code does not create any problems while running unit tests (because connections get established immediately) but is reportedly observed while connecting to a different machine. commit 8b76839(Move setsockopt TCP_NODELAY to when TCP is connected.) made changes to call setsockopt with TCP_NODELAY after TCP is connected only in lib/stream-ssl.c. We need the same change for stream-tcp too and this commit does that. Currently, a failure of setting TCP_NODELAY results in reporting the error and then closing the socket. This commit changes that behavior such that an error is reported if setting TCP_NODELAY fails, but the connection itself is not torn down. Signed-off-by: Gurucharan Shetty <gshetty@nicira.com> Acked-by: Ben Pfaff <blp@nicira.com>
134 lines
3.6 KiB
C
134 lines
3.6 KiB
C
/*
|
||
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
|
||
*
|
||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
* you may not use this file except in compliance with the License.
|
||
* You may obtain a copy of the License at:
|
||
*
|
||
* http://www.apache.org/licenses/LICENSE-2.0
|
||
*
|
||
* Unless required by applicable law or agreed to in writing, software
|
||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
* See the License for the specific language governing permissions and
|
||
* limitations under the License.
|
||
*/
|
||
|
||
#include <config.h>
|
||
#include "stream.h"
|
||
#include <errno.h>
|
||
#include <inttypes.h>
|
||
#include <netdb.h>
|
||
#include <poll.h>
|
||
#include <sys/socket.h>
|
||
#include <sys/types.h>
|
||
#include <sys/un.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <unistd.h>
|
||
#include "packets.h"
|
||
#include "poll-loop.h"
|
||
#include "socket-util.h"
|
||
#include "dirs.h"
|
||
#include "util.h"
|
||
#include "stream-provider.h"
|
||
#include "stream-fd.h"
|
||
#include "vlog.h"
|
||
|
||
VLOG_DEFINE_THIS_MODULE(stream_unix);
|
||
|
||
/* Active UNIX socket. */
|
||
|
||
static int
|
||
unix_open(const char *name, char *suffix, struct stream **streamp,
|
||
uint8_t dscp OVS_UNUSED)
|
||
{
|
||
char *connect_path;
|
||
int fd;
|
||
|
||
connect_path = abs_file_name(ovs_rundir(), suffix);
|
||
fd = make_unix_socket(SOCK_STREAM, true, NULL, connect_path);
|
||
|
||
if (fd < 0) {
|
||
VLOG_DBG("%s: connection failed (%s)",
|
||
connect_path, ovs_strerror(-fd));
|
||
free(connect_path);
|
||
return -fd;
|
||
}
|
||
|
||
free(connect_path);
|
||
return new_fd_stream(name, fd, check_connection_completion(fd),
|
||
AF_UNIX, streamp);
|
||
}
|
||
|
||
const struct stream_class unix_stream_class = {
|
||
"unix", /* name */
|
||
false, /* needs_probes */
|
||
unix_open, /* open */
|
||
NULL, /* close */
|
||
NULL, /* connect */
|
||
NULL, /* recv */
|
||
NULL, /* send */
|
||
NULL, /* run */
|
||
NULL, /* run_wait */
|
||
NULL, /* wait */
|
||
};
|
||
|
||
/* Passive UNIX socket. */
|
||
|
||
static int punix_accept(int fd, const struct sockaddr_storage *ss,
|
||
size_t ss_len, struct stream **streamp);
|
||
|
||
static int
|
||
punix_open(const char *name OVS_UNUSED, char *suffix,
|
||
struct pstream **pstreamp, uint8_t dscp OVS_UNUSED)
|
||
{
|
||
char *bind_path;
|
||
int fd, error;
|
||
|
||
bind_path = abs_file_name(ovs_rundir(), suffix);
|
||
fd = make_unix_socket(SOCK_STREAM, true, bind_path, NULL);
|
||
if (fd < 0) {
|
||
VLOG_ERR("%s: binding failed: %s", bind_path, ovs_strerror(errno));
|
||
free(bind_path);
|
||
return errno;
|
||
}
|
||
|
||
if (listen(fd, 64) < 0) {
|
||
error = errno;
|
||
VLOG_ERR("%s: listen: %s", name, ovs_strerror(error));
|
||
close(fd);
|
||
free(bind_path);
|
||
return error;
|
||
}
|
||
|
||
return new_fd_pstream(name, fd, punix_accept, NULL, bind_path, pstreamp);
|
||
}
|
||
|
||
static int
|
||
punix_accept(int fd, const struct sockaddr_storage *ss, size_t ss_len,
|
||
struct stream **streamp)
|
||
{
|
||
const struct sockaddr_un *sun = (const struct sockaddr_un *) ss;
|
||
int name_len = get_unix_name_len(ss_len);
|
||
char name[128];
|
||
|
||
if (name_len > 0) {
|
||
snprintf(name, sizeof name, "unix:%.*s", name_len, sun->sun_path);
|
||
} else {
|
||
strcpy(name, "unix");
|
||
}
|
||
return new_fd_stream(name, fd, 0, AF_UNIX, streamp);
|
||
}
|
||
|
||
const struct pstream_class punix_pstream_class = {
|
||
"punix",
|
||
false,
|
||
punix_open,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
};
|
||
|