All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 for-2.10 0/8] s390x: Basic support for 3270 devices
@ 2017-04-07 11:18 Cornelia Huck
  2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 1/8] chardev: Basic support for TN3270 Cornelia Huck
                   ` (7 more replies)
  0 siblings, 8 replies; 15+ messages in thread
From: Cornelia Huck @ 2017-04-07 11:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: borntraeger, agraf, pbonzini, marcandre.lureau, Cornelia Huck

Next version of the 3270 support patch set, originally sent in
February. Rebased on top of the current s390-next branch.

See http://wiki.qemu-project.org/Features/3270 for some information
on features, limitations and how to set this up.

I'd still like some acks for the first patch.

Changes v1 -> v2:
- qapi: added "since 2.10", removed "#optional"
- adapt to css id introspection patch and busid cleanup

Jing Liu (6):
  chardev: Basic support for TN3270
  s390x/css: Add an algorithm to find a free chpid
  s390x/3270: 3270 data stream handling
  s390x/3270: Add the TCP socket events handler for 3270
  s390x/3270: Detect for continued presence of a 3270 client
  s390x/3270: Mark non-migratable and enable the device

Yang Chen (2):
  s390x/3270: Add abstract emulated ccw-attached 3270 device
  s390x/3270: Add emulated terminal3270 device

 chardev/char-socket.c             |  76 +++++++---
 chardev/char.c                    |  11 +-
 default-configs/s390x-softmmu.mak |   1 +
 hw/char/Makefile.objs             |   1 +
 hw/char/terminal3270.c            | 293 ++++++++++++++++++++++++++++++++++++++
 hw/s390x/3270-ccw.c               | 174 ++++++++++++++++++++++
 hw/s390x/Makefile.objs            |   1 +
 hw/s390x/css.c                    |  24 ++++
 include/hw/s390x/3270-ccw.h       |  53 +++++++
 include/hw/s390x/css.h            |   2 +
 include/sysemu/char.h             |   8 ++
 qapi-schema.json                  |   3 +
 12 files changed, 625 insertions(+), 22 deletions(-)
 create mode 100644 hw/char/terminal3270.c
 create mode 100644 hw/s390x/3270-ccw.c
 create mode 100644 include/hw/s390x/3270-ccw.h

-- 
2.11.0

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PATCH v2 for-2.10 1/8] chardev: Basic support for TN3270
  2017-04-07 11:18 [Qemu-devel] [PATCH v2 for-2.10 0/8] s390x: Basic support for 3270 devices Cornelia Huck
@ 2017-04-07 11:18 ` Cornelia Huck
  2017-04-07 13:58   ` Eric Blake
                     ` (2 more replies)
  2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 2/8] s390x/css: Add an algorithm to find a free chpid Cornelia Huck
                   ` (6 subsequent siblings)
  7 siblings, 3 replies; 15+ messages in thread
From: Cornelia Huck @ 2017-04-07 11:18 UTC (permalink / raw)
  To: qemu-devel
  Cc: borntraeger, agraf, pbonzini, marcandre.lureau, Jing Liu,
	Yang Chen, Cornelia Huck

From: Jing Liu <liujbjl@linux.vnet.ibm.com>

This introduces basic support for TN3270, which needs to negotiate
three Telnet options during handshake:
  - End of Record
  - Binary Transmission
  - Terminal-Type

As a basic implementation, this simply ignores NOP and Interrupt
Process(IP) commands. More work should be done for them later.

For more details, please refer to RFC 854 and 1576.

Signed-off-by: Jing Liu <liujbjl@linux.vnet.ibm.com>
Signed-off-by: Yang Chen <bjcyang@linux.vnet.ibm.com>
Reviewed-by: QingFeng Hao <haoqf@linux.vnet.ibm.com>
Acked-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 chardev/char-socket.c | 76 +++++++++++++++++++++++++++++++++++++--------------
 chardev/char.c        | 11 ++++++--
 include/sysemu/char.h |  8 ++++++
 qapi-schema.json      |  3 ++
 4 files changed, 76 insertions(+), 22 deletions(-)

diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 36ab0d633a..175fb8c3ec 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -55,6 +55,7 @@ typedef struct {
     SocketAddress *addr;
     bool is_listen;
     bool is_telnet;
+    bool is_tn3270;
 
     guint reconnect_timer;
     int64_t reconnect_time;
@@ -141,19 +142,25 @@ static int tcp_chr_read_poll(void *opaque)
     return s->max_size;
 }
 
-#define IAC 255
-#define IAC_BREAK 243
 static void tcp_chr_process_IAC_bytes(Chardev *chr,
                                       SocketChardev *s,
                                       uint8_t *buf, int *size)
 {
-    /* Handle any telnet client's basic IAC options to satisfy char by
-     * char mode with no echo.  All IAC options will be removed from
-     * the buf and the do_telnetopt variable will be used to track the
-     * state of the width of the IAC information.
+    /* Handle any telnet or tn3270 client's basic IAC options.
+     * For telnet options, it satisfies char by char mode with no echo.
+     * For tn3270 options, it satisfies binary mode with EOR.
+     * All IAC options will be removed from the buf and the do_opt
+     * pointer will be used to track the state of the width of the
+     * IAC information.
      *
-     * IAC commands come in sets of 3 bytes with the exception of the
-     * "IAC BREAK" command and the double IAC.
+     * RFC854: "All TELNET commands consist of at least a two byte sequence.
+     * The commands dealing with option negotiation are three byte sequences,
+     * the third byte being the code for the option referenced."
+     * "IAC BREAK", "IAC IP", "IAC NOP" and the double IAC are two bytes.
+     * "IAC SB", "IAC SE" and "IAC EOR" are saved to split up data boundary
+     * for tn3270.
+     * NOP, Break and Interrupt Process(IP) might be encountered during a TN3270
+     * session, and NOP and IP need to be done later.
      */
 
     int i;
@@ -174,6 +181,18 @@ static void tcp_chr_process_IAC_bytes(Chardev *chr,
                     /* Handle IAC break commands by sending a serial break */
                     qemu_chr_be_event(chr, CHR_EVENT_BREAK);
                     s->do_telnetopt++;
+                } else if (s->is_tn3270 && ((unsigned char)buf[i] == IAC_EOR
+                           || (unsigned char)buf[i] == IAC_SB
+                           || (unsigned char)buf[i] == IAC_SE)
+                           && s->do_telnetopt == 2) {
+                    buf[j++] = IAC;
+                    buf[j++] = buf[i];
+                    s->do_telnetopt++;
+                } else if (s->is_tn3270 && ((unsigned char)buf[i] == IAC_IP
+                           || (unsigned char)buf[i] == IAC_NOP)
+                           && s->do_telnetopt == 2) {
+                    /* TODO: IP and NOP need to be implemented later. */
+                    s->do_telnetopt++;
                 }
                 s->do_telnetopt++;
             }
@@ -512,7 +531,7 @@ static void tcp_chr_update_read_handler(Chardev *chr,
 
 typedef struct {
     Chardev *chr;
-    char buf[12];
+    char buf[21];
     size_t buflen;
 } TCPChardevTelnetInit;
 
@@ -550,9 +569,6 @@ static void tcp_chr_telnet_init(Chardev *chr)
     TCPChardevTelnetInit *init = g_new0(TCPChardevTelnetInit, 1);
     size_t n = 0;
 
-    init->chr = chr;
-    init->buflen = 12;
-
 #define IACSET(x, a, b, c)                      \
     do {                                        \
         x[n++] = a;                             \
@@ -560,12 +576,26 @@ static void tcp_chr_telnet_init(Chardev *chr)
         x[n++] = c;                             \
     } while (0)
 
-    /* Prep the telnet negotion to put telnet in binary,
-     * no echo, single char mode */
-    IACSET(init->buf, 0xff, 0xfb, 0x01);  /* IAC WILL ECHO */
-    IACSET(init->buf, 0xff, 0xfb, 0x03);  /* IAC WILL Suppress go ahead */
-    IACSET(init->buf, 0xff, 0xfb, 0x00);  /* IAC WILL Binary */
-    IACSET(init->buf, 0xff, 0xfd, 0x00);  /* IAC DO Binary */
+    init->chr = chr;
+    if (!s->is_tn3270) {
+        init->buflen = 12;
+        /* Prep the telnet negotion to put telnet in binary,
+         * no echo, single char mode */
+        IACSET(init->buf, 0xff, 0xfb, 0x01);  /* IAC WILL ECHO */
+        IACSET(init->buf, 0xff, 0xfb, 0x03);  /* IAC WILL Suppress go ahead */
+        IACSET(init->buf, 0xff, 0xfb, 0x00);  /* IAC WILL Binary */
+        IACSET(init->buf, 0xff, 0xfd, 0x00);  /* IAC DO Binary */
+    } else {
+        init->buflen = 21;
+        /* Prep the TN3270 negotion based on RFC1576 */
+        IACSET(init->buf, 0xff, 0xfd, 0x19);  /* IAC DO EOR */
+        IACSET(init->buf, 0xff, 0xfb, 0x19);  /* IAC WILL EOR */
+        IACSET(init->buf, 0xff, 0xfd, 0x00);  /* IAC DO BINARY */
+        IACSET(init->buf, 0xff, 0xfb, 0x00);  /* IAC WILL BINARY */
+        IACSET(init->buf, 0xff, 0xfd, 0x18);  /* IAC DO TERMINAL TYPE */
+        IACSET(init->buf, 0xff, 0xfa, 0x18);  /* IAC SB TERMINAL TYPE */
+        IACSET(init->buf, 0x01, 0xff, 0xf0);  /* SEND IAC SE */
+    }
 
 #undef IACSET
 
@@ -585,7 +615,8 @@ static void tcp_chr_tls_handshake(QIOTask *task,
     if (qio_task_propagate_error(task, NULL)) {
         tcp_chr_disconnect(chr);
     } else {
-        if (s->do_telnetopt) {
+        /* tn3270 does not support TLS yet */
+        if (s->do_telnetopt && !s->is_tn3270) {
             tcp_chr_telnet_init(chr);
         } else {
             tcp_chr_connect(chr);
@@ -824,12 +855,14 @@ static void qmp_chardev_open_socket(Chardev *chr,
     bool do_nodelay     = sock->has_nodelay ? sock->nodelay : false;
     bool is_listen      = sock->has_server  ? sock->server  : true;
     bool is_telnet      = sock->has_telnet  ? sock->telnet  : false;
+    bool is_tn3270      = sock->has_tn3270  ? sock->tn3270  : false;
     bool is_waitconnect = sock->has_wait    ? sock->wait    : false;
     int64_t reconnect   = sock->has_reconnect ? sock->reconnect : 0;
     QIOChannelSocket *sioc = NULL;
 
     s->is_listen = is_listen;
     s->is_telnet = is_telnet;
+    s->is_tn3270 = is_tn3270;
     s->do_nodelay = do_nodelay;
     if (sock->tls_creds) {
         Object *creds;
@@ -879,7 +912,7 @@ static void qmp_chardev_open_socket(Chardev *chr,
                                          addr, is_listen, is_telnet);
 
     if (is_listen) {
-        if (is_telnet) {
+        if (is_telnet || is_tn3270) {
             s->do_telnetopt = 1;
         }
     } else if (reconnect > 0) {
@@ -933,6 +966,7 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
     bool is_listen      = qemu_opt_get_bool(opts, "server", false);
     bool is_waitconnect = is_listen && qemu_opt_get_bool(opts, "wait", true);
     bool is_telnet      = qemu_opt_get_bool(opts, "telnet", false);
+    bool is_tn3270      = qemu_opt_get_bool(opts, "tn3270", false);
     bool do_nodelay     = !qemu_opt_get_bool(opts, "delay", true);
     int64_t reconnect   = qemu_opt_get_number(opts, "reconnect", 0);
     const char *path = qemu_opt_get(opts, "path");
@@ -968,6 +1002,8 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
     sock->server = is_listen;
     sock->has_telnet = true;
     sock->telnet = is_telnet;
+    sock->has_tn3270 = true;
+    sock->tn3270 = is_tn3270;
     sock->has_wait = true;
     sock->wait = is_waitconnect;
     sock->has_reconnect = true;
diff --git a/chardev/char.c b/chardev/char.c
index 3df116350b..309734f2b7 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -696,7 +696,8 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
         return opts;
     }
     if (strstart(filename, "tcp:", &p) ||
-        strstart(filename, "telnet:", &p)) {
+        strstart(filename, "telnet:", &p) ||
+        strstart(filename, "tn3270:", &p)) {
         if (sscanf(p, "%64[^:]:%32[^,]%n", host, port, &pos) < 2) {
             host[0] = 0;
             if (sscanf(p, ":%32[^,]%n", port, &pos) < 1)
@@ -712,8 +713,11 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
                 goto fail;
             }
         }
-        if (strstart(filename, "telnet:", &p))
+        if (strstart(filename, "telnet:", &p)) {
             qemu_opt_set(opts, "telnet", "on", &error_abort);
+        } else if (strstart(filename, "tn3270:", &p)) {
+            qemu_opt_set(opts, "tn3270", "on", &error_abort);
+        }
         return opts;
     }
     if (strstart(filename, "udp:", &p)) {
@@ -1177,6 +1181,9 @@ QemuOptsList qemu_chardev_opts = {
             .name = "telnet",
             .type = QEMU_OPT_BOOL,
         },{
+            .name = "tn3270",
+            .type = QEMU_OPT_BOOL,
+        },{
             .name = "tls-creds",
             .type = QEMU_OPT_STRING,
         },{
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index 450881d42c..f6d5cd0c9b 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -7,6 +7,14 @@
 #include "qemu/bitmap.h"
 #include "qom/object.h"
 
+#define IAC_EOR 239
+#define IAC_SE 240
+#define IAC_NOP 241
+#define IAC_BREAK 243
+#define IAC_IP 244
+#define IAC_SB 250
+#define IAC 255
+
 /* character device */
 
 typedef enum {
diff --git a/qapi-schema.json b/qapi-schema.json
index 250e4dc49b..f0302958ce 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -4874,6 +4874,8 @@
 # @nodelay: set TCP_NODELAY socket option (default: false)
 # @telnet: enable telnet protocol on server
 #          sockets (default: false)
+# @tn3270: enable tn3270 protocol on server
+#          sockets (default: false) (Since: 2.10)
 # @reconnect: For a client socket, if a socket is disconnected,
 #          then attempt a reconnect after the given number of seconds.
 #          Setting this to zero disables this function. (default: 0)
@@ -4887,6 +4889,7 @@
                                      '*wait'      : 'bool',
                                      '*nodelay'   : 'bool',
                                      '*telnet'    : 'bool',
+                                     '*tn3270'    : 'bool',
                                      '*reconnect' : 'int' },
   'base': 'ChardevCommon' }
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PATCH v2 for-2.10 2/8] s390x/css: Add an algorithm to find a free chpid
  2017-04-07 11:18 [Qemu-devel] [PATCH v2 for-2.10 0/8] s390x: Basic support for 3270 devices Cornelia Huck
  2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 1/8] chardev: Basic support for TN3270 Cornelia Huck
@ 2017-04-07 11:18 ` Cornelia Huck
  2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 3/8] s390x/3270: Add abstract emulated ccw-attached 3270 device Cornelia Huck
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Cornelia Huck @ 2017-04-07 11:18 UTC (permalink / raw)
  To: qemu-devel
  Cc: borntraeger, agraf, pbonzini, marcandre.lureau, Jing Liu, Cornelia Huck

From: Jing Liu <liujbjl@linux.vnet.ibm.com>

This introduces a function named css_find_free_chpid() to find a
free channel path. Because virtio-ccw device used zero as its
channel path number, it would be sensible to skip the reserved one
and search upwards.

Signed-off-by: Jing Liu <liujbjl@linux.vnet.ibm.com>
Reviewed-by: QingFeng Hao <haoqf@linux.vnet.ibm.com>
Reviewed-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 hw/s390x/css.c         | 21 +++++++++++++++++++++
 include/hw/s390x/css.h |  2 ++
 2 files changed, 23 insertions(+)

diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index c03bb20bc9..d94498a97b 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -1302,6 +1302,27 @@ bool css_schid_final(int m, uint8_t cssid, uint8_t ssid, uint16_t schid)
                                  (MAX_SCHID + 1) / sizeof(unsigned long));
 }
 
+unsigned int css_find_free_chpid(uint8_t cssid)
+{
+    CssImage *css = channel_subsys.css[cssid];
+    unsigned int chpid;
+
+    if (!css) {
+        return MAX_CHPID + 1;
+    }
+
+    for (chpid = 0; chpid <= MAX_CHPID; chpid++) {
+        /* skip reserved chpid */
+        if (chpid == VIRTIO_CCW_CHPID) {
+            continue;
+        }
+        if (!css->chpids[chpid].in_use) {
+            return chpid;
+        }
+    }
+    return MAX_CHPID + 1;
+}
+
 static int css_add_virtual_chpid(uint8_t cssid, uint8_t chpid, uint8_t type)
 {
     CssImage *css;
diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h
index f1f0d7f07a..e61fa74d9b 100644
--- a/include/hw/s390x/css.h
+++ b/include/hw/s390x/css.h
@@ -28,6 +28,7 @@
 #define MAX_CIWS 62
 
 #define VIRTUAL_CSSID 0xfe
+#define VIRTIO_CCW_CHPID 0   /* used by convention */
 
 typedef struct CIW {
     uint8_t type;
@@ -115,6 +116,7 @@ bool css_devno_used(uint8_t cssid, uint8_t ssid, uint16_t devno);
 void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid,
                       uint16_t devno, SubchDev *sch);
 void css_sch_build_virtual_schib(SubchDev *sch, uint8_t chpid, uint8_t type);
+unsigned int css_find_free_chpid(uint8_t cssid);
 uint16_t css_build_subchannel_id(SubchDev *sch);
 void css_reset(void);
 void css_reset_sch(SubchDev *sch);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PATCH v2 for-2.10 3/8] s390x/3270: Add abstract emulated ccw-attached 3270 device
  2017-04-07 11:18 [Qemu-devel] [PATCH v2 for-2.10 0/8] s390x: Basic support for 3270 devices Cornelia Huck
  2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 1/8] chardev: Basic support for TN3270 Cornelia Huck
  2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 2/8] s390x/css: Add an algorithm to find a free chpid Cornelia Huck
@ 2017-04-07 11:18 ` Cornelia Huck
  2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 4/8] s390x/3270: Add emulated terminal3270 device Cornelia Huck
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Cornelia Huck @ 2017-04-07 11:18 UTC (permalink / raw)
  To: qemu-devel
  Cc: borntraeger, agraf, pbonzini, marcandre.lureau, Yang Chen,
	Jing Liu, Cornelia Huck

From: Yang Chen <bjcyang@linux.vnet.ibm.com>

This introduces the infrastructure for the emulated 3270
devices, which will be attached to the virtual-css-bus.

Signed-off-by: Yang Chen <bjcyang@linux.vnet.ibm.com>
Signed-off-by: Jing Liu <liujbjl@linux.vnet.ibm.com>
Reviewed-by: QingFeng Hao <haoqf@linux.vnet.ibm.com>
Reviewed-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 hw/s390x/3270-ccw.c         | 99 +++++++++++++++++++++++++++++++++++++++++++++
 hw/s390x/Makefile.objs      |  1 +
 include/hw/s390x/3270-ccw.h | 44 ++++++++++++++++++++
 3 files changed, 144 insertions(+)
 create mode 100644 hw/s390x/3270-ccw.c
 create mode 100644 include/hw/s390x/3270-ccw.h

diff --git a/hw/s390x/3270-ccw.c b/hw/s390x/3270-ccw.c
new file mode 100644
index 0000000000..47b9e89bb7
--- /dev/null
+++ b/hw/s390x/3270-ccw.c
@@ -0,0 +1,99 @@
+/*
+ * Emulated ccw-attached 3270 implementation
+ *
+ * Copyright 2017 IBM Corp.
+ * Author(s): Yang Chen <bjcyang@linux.vnet.ibm.com>
+ *            Jing Liu <liujbjl@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "cpu.h"
+#include "hw/s390x/css.h"
+#include "hw/s390x/css-bridge.h"
+#include "hw/s390x/3270-ccw.h"
+
+static void emulated_ccw_3270_realize(DeviceState *ds, Error **errp)
+{
+    uint16_t chpid;
+    EmulatedCcw3270Device *dev = EMULATED_CCW_3270(ds);
+    EmulatedCcw3270Class *ck = EMULATED_CCW_3270_GET_CLASS(dev);
+    CcwDevice *cdev = CCW_DEVICE(ds);
+    CCWDeviceClass *cdk = CCW_DEVICE_GET_CLASS(cdev);
+    SubchDev *sch = css_create_virtual_sch(cdev->devno, errp);
+    Error *err = NULL;
+
+    if (!sch) {
+        return;
+    }
+
+    if (!ck->init) {
+        goto out_err;
+    }
+
+    sch->driver_data = dev;
+    cdev->sch = sch;
+    chpid = css_find_free_chpid(sch->cssid);
+
+    if (chpid > MAX_CHPID) {
+        error_setg(&err, "No available chpid to use.");
+        goto out_err;
+    }
+
+    sch->id.reserved = 0xff;
+    sch->id.cu_type = EMULATED_CCW_3270_CU_TYPE;
+    css_sch_build_virtual_schib(sch, (uint8_t)chpid,
+                                EMULATED_CCW_3270_CHPID_TYPE);
+
+    ck->init(dev, &err);
+    if (err) {
+        goto out_err;
+    }
+
+    cdk->realize(cdev, &err);
+    if (err) {
+        goto out_err;
+    }
+
+    return;
+
+out_err:
+    error_propagate(errp, err);
+    css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
+    cdev->sch = NULL;
+    g_free(sch);
+}
+
+static Property emulated_ccw_3270_properties[] = {
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void emulated_ccw_3270_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->props = emulated_ccw_3270_properties;
+    dc->bus_type = TYPE_VIRTUAL_CSS_BUS;
+    dc->realize = emulated_ccw_3270_realize;
+    dc->hotpluggable = false;
+}
+
+static const TypeInfo emulated_ccw_3270_info = {
+    .name = TYPE_EMULATED_CCW_3270,
+    .parent = TYPE_CCW_DEVICE,
+    .instance_size = sizeof(EmulatedCcw3270Device),
+    .class_init = emulated_ccw_3270_class_init,
+    .class_size = sizeof(EmulatedCcw3270Class),
+    .abstract = true,
+};
+
+static void emulated_ccw_register(void)
+{
+    type_register_static(&emulated_ccw_3270_info);
+}
+
+type_init(emulated_ccw_register)
diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs
index 41ac4ec325..36bd4b1645 100644
--- a/hw/s390x/Makefile.objs
+++ b/hw/s390x/Makefile.objs
@@ -7,6 +7,7 @@ obj-y += sclpcpu.o
 obj-y += ipl.o
 obj-y += css.o
 obj-y += s390-virtio-ccw.o
+obj-y += 3270-ccw.o
 obj-y += virtio-ccw.o
 obj-y += css-bridge.o
 obj-y += ccw-device.o
diff --git a/include/hw/s390x/3270-ccw.h b/include/hw/s390x/3270-ccw.h
new file mode 100644
index 0000000000..45ea515e9f
--- /dev/null
+++ b/include/hw/s390x/3270-ccw.h
@@ -0,0 +1,44 @@
+/*
+ * Emulated ccw-attached 3270 definitions
+ *
+ * Copyright 2017 IBM Corp.
+ * Author(s): Yang Chen <bjcyang@linux.vnet.ibm.com>
+ *            Jing Liu <liujbjl@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#ifndef HW_S390X_3270_CCW_H
+#define HW_S390X_3270_CCW_H
+
+#include "hw/sysbus.h"
+#include "hw/s390x/css.h"
+#include "hw/s390x/ccw-device.h"
+
+#define EMULATED_CCW_3270_CU_TYPE 0x3270
+#define EMULATED_CCW_3270_CHPID_TYPE 0x1a
+
+#define TYPE_EMULATED_CCW_3270 "emulated-ccw-3270"
+#define EMULATED_CCW_3270(obj) \
+     OBJECT_CHECK(EmulatedCcw3270Device, (obj), TYPE_EMULATED_CCW_3270)
+#define EMULATED_CCW_3270_CLASS(klass) \
+     OBJECT_CLASS_CHECK(EmulatedCcw3270Class, (klass), TYPE_EMULATED_CCW_3270)
+#define EMULATED_CCW_3270_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(EmulatedCcw3270Class, (obj), TYPE_EMULATED_CCW_3270)
+
+typedef struct EmulatedCcw3270Device {
+    CcwDevice parent_obj;
+} EmulatedCcw3270Device;
+
+typedef struct EmulatedCcw3270Class {
+    CCWDeviceClass parent_class;
+
+    void (*init)(EmulatedCcw3270Device *, Error **);
+    int (*read_payload_3270)(EmulatedCcw3270Device *, uint32_t, uint16_t);
+    int (*write_payload_3270)(EmulatedCcw3270Device *, uint8_t, uint32_t,
+                              uint16_t);
+} EmulatedCcw3270Class;
+
+#endif
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PATCH v2 for-2.10 4/8] s390x/3270: Add emulated terminal3270 device
  2017-04-07 11:18 [Qemu-devel] [PATCH v2 for-2.10 0/8] s390x: Basic support for 3270 devices Cornelia Huck
                   ` (2 preceding siblings ...)
  2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 3/8] s390x/3270: Add abstract emulated ccw-attached 3270 device Cornelia Huck
@ 2017-04-07 11:18 ` Cornelia Huck
  2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 5/8] s390x/3270: 3270 data stream handling Cornelia Huck
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Cornelia Huck @ 2017-04-07 11:18 UTC (permalink / raw)
  To: qemu-devel
  Cc: borntraeger, agraf, pbonzini, marcandre.lureau, Yang Chen,
	Jing Liu, Cornelia Huck

From: Yang Chen <bjcyang@linux.vnet.ibm.com>

This is a basic implementation of the emulated ccw-attached 3270
called x-terminal3270, which provides visibility of the device in
the qemu monitor and guest. The x prefix indicates that this is
just an experimental implementation for the current stage. This
device will not be compiled until the basic functions are available.

Signed-off-by: Yang Chen <bjcyang@linux.vnet.ibm.com>
Signed-off-by: Jing Liu <liujbjl@linux.vnet.ibm.com>
Reviewed-by: QingFeng Hao <haoqf@linux.vnet.ibm.com>
Reviewed-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 hw/char/terminal3270.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)
 create mode 100644 hw/char/terminal3270.c

diff --git a/hw/char/terminal3270.c b/hw/char/terminal3270.c
new file mode 100644
index 0000000000..bef3812c18
--- /dev/null
+++ b/hw/char/terminal3270.c
@@ -0,0 +1,54 @@
+/*
+ * Terminal 3270 implementation
+ *
+ * Copyright 2017 IBM Corp.
+ *
+ * Authors: Yang Chen <bjcyang@linux.vnet.ibm.com>
+ *          Jing Liu <liujbjl@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/s390x/3270-ccw.h"
+
+typedef struct Terminal3270 {
+    EmulatedCcw3270Device cdev;
+} Terminal3270;
+
+#define TYPE_TERMINAL_3270 "x-terminal3270"
+
+static void terminal_init(EmulatedCcw3270Device *dev, Error **errp)
+{
+    static bool terminal_available;
+
+    if (terminal_available) {
+        error_setg(errp, "Multiple 3270 terminals are not supported.");
+        return;
+    }
+    terminal_available = true;
+}
+
+static void terminal_class_init(ObjectClass *klass, void *data)
+{
+    EmulatedCcw3270Class *ck = EMULATED_CCW_3270_CLASS(klass);
+
+    ck->init = terminal_init;
+}
+
+static const TypeInfo ccw_terminal_info = {
+    .name = TYPE_TERMINAL_3270,
+    .parent = TYPE_EMULATED_CCW_3270,
+    .instance_size = sizeof(Terminal3270),
+    .class_init = terminal_class_init,
+    .class_size = sizeof(EmulatedCcw3270Class),
+};
+
+static void register_types(void)
+{
+    type_register_static(&ccw_terminal_info);
+}
+
+type_init(register_types)
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PATCH v2 for-2.10 5/8] s390x/3270: 3270 data stream handling
  2017-04-07 11:18 [Qemu-devel] [PATCH v2 for-2.10 0/8] s390x: Basic support for 3270 devices Cornelia Huck
                   ` (3 preceding siblings ...)
  2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 4/8] s390x/3270: Add emulated terminal3270 device Cornelia Huck
@ 2017-04-07 11:18 ` Cornelia Huck
  2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 6/8] s390x/3270: Add the TCP socket events handler for 3270 Cornelia Huck
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Cornelia Huck @ 2017-04-07 11:18 UTC (permalink / raw)
  To: qemu-devel
  Cc: borntraeger, agraf, pbonzini, marcandre.lureau, Jing Liu,
	Yang Chen, Cornelia Huck

From: Jing Liu <liujbjl@linux.vnet.ibm.com>

This introduces the input and output handlers for 3270 device, setting
up the data tunnel among guest kernel, qemu and the 3270 client.

After the client connected and TN3270 handshake done, signal the not-ready
to ready status by an unsolicited device-end interrupt, and then the 3270
data stream could be handled correctly between the channel and socket.
Multiple commands generated by "Reset" key on x3270 are not supported now,
just simply terminate the connection.

Signed-off-by: Jing Liu <liujbjl@linux.vnet.ibm.com>
Signed-off-by: Yang Chen <bjcyang@linux.vnet.ibm.com>
Reviewed-by: QingFeng Hao <haoqf@linux.vnet.ibm.com>
Reviewed-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 hw/char/terminal3270.c      | 180 ++++++++++++++++++++++++++++++++++++++++++++
 hw/s390x/3270-ccw.c         |  75 ++++++++++++++++++
 hw/s390x/css.c              |   3 +
 include/hw/s390x/3270-ccw.h |   9 +++
 4 files changed, 267 insertions(+)

diff --git a/hw/char/terminal3270.c b/hw/char/terminal3270.c
index bef3812c18..55eed5622a 100644
--- a/hw/char/terminal3270.c
+++ b/hw/char/terminal3270.c
@@ -12,16 +12,114 @@
  */
 
 #include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "sysemu/char.h"
 #include "hw/s390x/3270-ccw.h"
 
+/* Enough spaces for different window sizes. */
+#define INPUT_BUFFER_SIZE  1000
+/*
+ * 1 for header, 1024*2 for datastream, 2 for tail
+ * Reserve enough spaces for telnet IAC escape.
+ */
+#define OUTPUT_BUFFER_SIZE 2051
+
 typedef struct Terminal3270 {
     EmulatedCcw3270Device cdev;
+    CharBackend chr;
+    uint8_t inv[INPUT_BUFFER_SIZE];
+    uint8_t outv[OUTPUT_BUFFER_SIZE];
+    int in_len;
+    int out_len;
+    bool handshake_done;
 } Terminal3270;
 
 #define TYPE_TERMINAL_3270 "x-terminal3270"
+#define TERMINAL_3270(obj) \
+        OBJECT_CHECK(Terminal3270, (obj), TYPE_TERMINAL_3270)
+
+static int terminal_can_read(void *opaque)
+{
+    Terminal3270 *t = opaque;
+
+    return INPUT_BUFFER_SIZE - t->in_len;
+}
+
+/*
+ * Protocol handshake done,
+ * signal guest by an unsolicited DE irq.
+ */
+static void TN3270_handshake_done(Terminal3270 *t)
+{
+    CcwDevice *ccw_dev = CCW_DEVICE(t);
+    SubchDev *sch = ccw_dev->sch;
+
+    t->handshake_done = true;
+    sch->curr_status.scsw.dstat = SCSW_DSTAT_DEVICE_END;
+    css_conditional_io_interrupt(sch);
+}
+
+/*
+ * Receive inbound data from socket.
+ * For data given to guest, drop the data boundary IAC, IAC_EOR.
+ * TODO:
+ * Using "Reset" key on x3270 may result multiple commands in one packet.
+ * This usually happens when the user meets a poor traffic of the network.
+ * As of now, for such case, we simply terminate the connection,
+ * and we should come back here later with a better solution.
+ */
+static void terminal_read(void *opaque, const uint8_t *buf, int size)
+{
+    Terminal3270 *t = opaque;
+    CcwDevice *ccw_dev = CCW_DEVICE(t);
+    SubchDev *sch = ccw_dev->sch;
+    int end;
+
+    assert(size <= (INPUT_BUFFER_SIZE - t->in_len));
+
+    memcpy(&t->inv[t->in_len], buf, size);
+    t->in_len += size;
+    if (t->in_len < 2) {
+        return;
+    }
+
+    if (!t->handshake_done) {
+        /*
+         * Receiving Terminal Type is the last step of handshake.
+         * The data format: IAC SB Terminal-Type IS <terminal type> IAC SE
+         * The code for Terminal-Type is 0x18, for IS is 0.
+         * Simply check the data format and mark handshake_done.
+         */
+        if (t->in_len > 6 && t->inv[2] == 0x18 && t->inv[3] == 0x0 &&
+            t->inv[t->in_len - 2] == IAC && t->inv[t->in_len - 1] == IAC_SE) {
+            TN3270_handshake_done(t);
+            t->in_len = 0;
+        }
+        return;
+    }
+
+    for (end = 0; end < t->in_len - 1; end++) {
+        if (t->inv[end] == IAC && t->inv[end + 1] == IAC_EOR) {
+            break;
+        }
+    }
+    if (end == t->in_len - 2) {
+        /* Data is valid for consuming. */
+        t->in_len -= 2;
+        sch->curr_status.scsw.dstat = SCSW_DSTAT_ATTENTION;
+        css_conditional_io_interrupt(sch);
+    } else if (end < t->in_len - 2) {
+        /* "Reset" key is used. */
+        qemu_chr_fe_disconnect(&t->chr);
+    } else {
+        /* Gathering data. */
+        return;
+    }
+}
 
 static void terminal_init(EmulatedCcw3270Device *dev, Error **errp)
 {
+    Terminal3270 *t = TERMINAL_3270(dev);
     static bool terminal_available;
 
     if (terminal_available) {
@@ -29,13 +127,95 @@ static void terminal_init(EmulatedCcw3270Device *dev, Error **errp)
         return;
     }
     terminal_available = true;
+    qemu_chr_fe_set_handlers(&t->chr, terminal_can_read,
+                             terminal_read, NULL, t, NULL, true);
+}
+
+static int read_payload_3270(EmulatedCcw3270Device *dev, uint32_t cda,
+                             uint16_t count)
+{
+    Terminal3270 *t = TERMINAL_3270(dev);
+    int len;
+
+    len = MIN(count, t->in_len);
+    cpu_physical_memory_write(cda, t->inv, len);
+    t->in_len -= len;
+
+    return len;
+}
+
+/* TN3270 uses binary transmission, which needs escape IAC to IAC IAC */
+static int insert_IAC_escape_char(uint8_t *outv, int out_len)
+{
+    int IAC_num = 0, new_out_len, i, j;
+
+    for (i = 0; i < out_len; i++) {
+        if (outv[i] == IAC) {
+            IAC_num++;
+        }
+    }
+    if (IAC_num == 0) {
+        return out_len;
+    }
+    new_out_len = out_len + IAC_num;
+    for (i = out_len - 1, j = new_out_len - 1; j > i && i >= 0; i--, j--) {
+        outv[j] = outv[i];
+        if (outv[i] == IAC) {
+            outv[--j] = IAC;
+        }
+    }
+    return new_out_len;
 }
 
+/*
+ * Write 3270 outbound to socket.
+ * Return the count of 3270 data field if succeeded, zero if failed.
+ */
+static int write_payload_3270(EmulatedCcw3270Device *dev, uint8_t cmd,
+                              uint32_t cda, uint16_t count)
+{
+    Terminal3270 *t = TERMINAL_3270(dev);
+    int retval = 0;
+
+    assert(count <= (OUTPUT_BUFFER_SIZE - 3) / 2);
+
+    if (!t->handshake_done) {
+        /*
+         * Before having finished 3270 negotiation,
+         * sending outbound data is prohibited.
+         */
+        return 0;
+    }
+    if (!qemu_chr_fe_get_driver(&t->chr)) {
+        /* We just say we consumed all data if there's no backend. */
+        return count;
+    }
+    t->outv[0] = cmd;
+    cpu_physical_memory_read(cda, &t->outv[1], count);
+    t->out_len = count + 1;
+
+    t->out_len = insert_IAC_escape_char(t->outv, t->out_len);
+    t->outv[t->out_len++] = IAC;
+    t->outv[t->out_len++] = IAC_EOR;
+
+    retval = qemu_chr_fe_write_all(&t->chr, t->outv, t->out_len);
+    return (retval <= 0) ? 0 : (retval - 3);
+}
+
+static Property terminal_properties[] = {
+    DEFINE_PROP_CHR("chardev", Terminal3270, chr),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
 static void terminal_class_init(ObjectClass *klass, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(klass);
     EmulatedCcw3270Class *ck = EMULATED_CCW_3270_CLASS(klass);
 
+    dc->props = terminal_properties;
     ck->init = terminal_init;
+    ck->read_payload_3270 = read_payload_3270;
+    ck->write_payload_3270 = write_payload_3270;
 }
 
 static const TypeInfo ccw_terminal_info = {
diff --git a/hw/s390x/3270-ccw.c b/hw/s390x/3270-ccw.c
index 47b9e89bb7..a7a5b412e4 100644
--- a/hw/s390x/3270-ccw.c
+++ b/hw/s390x/3270-ccw.c
@@ -17,6 +17,80 @@
 #include "hw/s390x/css-bridge.h"
 #include "hw/s390x/3270-ccw.h"
 
+/* Handle READ ccw commands from guest */
+static int handle_payload_3270_read(EmulatedCcw3270Device *dev, CCW1 *ccw)
+{
+    EmulatedCcw3270Class *ck = EMULATED_CCW_3270_GET_CLASS(dev);
+    CcwDevice *ccw_dev = CCW_DEVICE(dev);
+    int len;
+
+    if (!ccw->cda) {
+        return -EFAULT;
+    }
+
+    len = ck->read_payload_3270(dev, ccw->cda, ccw->count);
+    ccw_dev->sch->curr_status.scsw.count = ccw->count - len;
+
+    return 0;
+}
+
+/* Handle WRITE ccw commands to write data to client */
+static int handle_payload_3270_write(EmulatedCcw3270Device *dev, CCW1 *ccw)
+{
+    EmulatedCcw3270Class *ck = EMULATED_CCW_3270_GET_CLASS(dev);
+    CcwDevice *ccw_dev = CCW_DEVICE(dev);
+    int len;
+
+    if (!ccw->cda) {
+        return -EFAULT;
+    }
+
+    len = ck->write_payload_3270(dev, ccw->cmd_code, ccw->cda, ccw->count);
+
+    if (len <= 0) {
+        return -EIO;
+    }
+
+    ccw_dev->sch->curr_status.scsw.count = ccw->count - len;
+    return 0;
+}
+
+static int emulated_ccw_3270_cb(SubchDev *sch, CCW1 ccw)
+{
+    int rc = 0;
+    EmulatedCcw3270Device *dev = sch->driver_data;
+
+    switch (ccw.cmd_code) {
+    case TC_WRITESF:
+    case TC_WRITE:
+    case TC_EWRITE:
+    case TC_EWRITEA:
+        rc = handle_payload_3270_write(dev, &ccw);
+        break;
+    case TC_RDBUF:
+    case TC_READMOD:
+        rc = handle_payload_3270_read(dev, &ccw);
+        break;
+    default:
+        rc = -ENOSYS;
+        break;
+    }
+
+    if (rc == -EIO) {
+        /* I/O error, specific devices generate specific conditions */
+        SCSW *s = &sch->curr_status.scsw;
+
+        sch->curr_status.scsw.dstat = SCSW_DSTAT_UNIT_CHECK;
+        sch->sense_data[0] = 0x40;    /* intervention-req */
+        s->ctrl &= ~SCSW_ACTL_START_PEND;
+        s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
+        s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
+                   SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
+    }
+
+    return rc;
+}
+
 static void emulated_ccw_3270_realize(DeviceState *ds, Error **errp)
 {
     uint16_t chpid;
@@ -48,6 +122,7 @@ static void emulated_ccw_3270_realize(DeviceState *ds, Error **errp)
     sch->id.cu_type = EMULATED_CCW_3270_CU_TYPE;
     css_sch_build_virtual_schib(sch, (uint8_t)chpid,
                                 EMULATED_CCW_3270_CHPID_TYPE);
+    sch->ccw_cb = emulated_ccw_3270_cb;
 
     ck->init(dev, &err);
     if (err) {
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index d94498a97b..15c4f4b249 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -576,6 +576,9 @@ static void sch_handle_start_func(SubchDev *sch, ORB *orb)
             s->dstat = SCSW_DSTAT_CHANNEL_END | SCSW_DSTAT_DEVICE_END;
             s->cpa = sch->channel_prog + 8;
             break;
+        case -EIO:
+            /* I/O errors, status depends on specific devices */
+            break;
         case -ENOSYS:
             /* unsupported command, generate unit check (command reject) */
             s->ctrl &= ~SCSW_ACTL_START_PEND;
diff --git a/include/hw/s390x/3270-ccw.h b/include/hw/s390x/3270-ccw.h
index 45ea515e9f..46bee2533c 100644
--- a/include/hw/s390x/3270-ccw.h
+++ b/include/hw/s390x/3270-ccw.h
@@ -21,6 +21,15 @@
 #define EMULATED_CCW_3270_CHPID_TYPE 0x1a
 
 #define TYPE_EMULATED_CCW_3270 "emulated-ccw-3270"
+
+/* Local Channel Commands */
+#define TC_WRITE   0x01         /* Write */
+#define TC_RDBUF   0x02         /* Read buffer */
+#define TC_EWRITE  0x05         /* Erase write */
+#define TC_READMOD 0x06         /* Read modified */
+#define TC_EWRITEA 0x0d         /* Erase write alternate */
+#define TC_WRITESF 0x11         /* Write structured field */
+
 #define EMULATED_CCW_3270(obj) \
      OBJECT_CHECK(EmulatedCcw3270Device, (obj), TYPE_EMULATED_CCW_3270)
 #define EMULATED_CCW_3270_CLASS(klass) \
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PATCH v2 for-2.10 6/8] s390x/3270: Add the TCP socket events handler for 3270
  2017-04-07 11:18 [Qemu-devel] [PATCH v2 for-2.10 0/8] s390x: Basic support for 3270 devices Cornelia Huck
                   ` (4 preceding siblings ...)
  2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 5/8] s390x/3270: 3270 data stream handling Cornelia Huck
@ 2017-04-07 11:18 ` Cornelia Huck
  2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 7/8] s390x/3270: Detect for continued presence of a 3270 client Cornelia Huck
  2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 8/8] s390x/3270: Mark non-migratable and enable the device Cornelia Huck
  7 siblings, 0 replies; 15+ messages in thread
From: Cornelia Huck @ 2017-04-07 11:18 UTC (permalink / raw)
  To: qemu-devel
  Cc: borntraeger, agraf, pbonzini, marcandre.lureau, Jing Liu, Cornelia Huck

From: Jing Liu <liujbjl@linux.vnet.ibm.com>

This introduces a chr_event handler to handle the 3270 connection
and disconnection events.

Signed-off-by: Jing Liu <liujbjl@linux.vnet.ibm.com>
Reviewed-by: QingFeng Hao <haoqf@linux.vnet.ibm.com>
Reviewed-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 hw/char/terminal3270.c | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/hw/char/terminal3270.c b/hw/char/terminal3270.c
index 55eed5622a..450608e3c3 100644
--- a/hw/char/terminal3270.c
+++ b/hw/char/terminal3270.c
@@ -117,6 +117,32 @@ static void terminal_read(void *opaque, const uint8_t *buf, int size)
     }
 }
 
+static void chr_event(void *opaque, int event)
+{
+    Terminal3270 *t = opaque;
+    CcwDevice *ccw_dev = CCW_DEVICE(t);
+    SubchDev *sch = ccw_dev->sch;
+
+    /* Ensure the initial status correct, always reset them. */
+    t->in_len = 0;
+    t->out_len = 0;
+    t->handshake_done = false;
+
+    switch (event) {
+    case CHR_EVENT_OPENED:
+        /*
+         * 3270 does handshake firstly by the negotiate options in
+         * char-socket.c. Once qemu receives the terminal-type of the
+         * client, mark handshake done and trigger everything rolling again.
+         */
+        break;
+    case CHR_EVENT_CLOSED:
+        sch->curr_status.scsw.dstat = SCSW_DSTAT_DEVICE_END;
+        css_conditional_io_interrupt(sch);
+        break;
+    }
+}
+
 static void terminal_init(EmulatedCcw3270Device *dev, Error **errp)
 {
     Terminal3270 *t = TERMINAL_3270(dev);
@@ -128,7 +154,7 @@ static void terminal_init(EmulatedCcw3270Device *dev, Error **errp)
     }
     terminal_available = true;
     qemu_chr_fe_set_handlers(&t->chr, terminal_can_read,
-                             terminal_read, NULL, t, NULL, true);
+                             terminal_read, chr_event, t, NULL, true);
 }
 
 static int read_payload_3270(EmulatedCcw3270Device *dev, uint32_t cda,
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PATCH v2 for-2.10 7/8] s390x/3270: Detect for continued presence of a 3270 client
  2017-04-07 11:18 [Qemu-devel] [PATCH v2 for-2.10 0/8] s390x: Basic support for 3270 devices Cornelia Huck
                   ` (5 preceding siblings ...)
  2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 6/8] s390x/3270: Add the TCP socket events handler for 3270 Cornelia Huck
@ 2017-04-07 11:18 ` Cornelia Huck
  2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 8/8] s390x/3270: Mark non-migratable and enable the device Cornelia Huck
  7 siblings, 0 replies; 15+ messages in thread
From: Cornelia Huck @ 2017-04-07 11:18 UTC (permalink / raw)
  To: qemu-devel
  Cc: borntraeger, agraf, pbonzini, marcandre.lureau, Jing Liu, Cornelia Huck

From: Jing Liu <liujbjl@linux.vnet.ibm.com>

To ensure that we do not keep any 3270 sockets where the client is not
connected anymore, we send a packet with the timing mark option after
ten minutes of client inactivity. If the client does not answer it,
then the socket will be closed automatically.

This helps to ensure that there is no half-open situation on the 3270
socket.

Signed-off-by: Jing Liu <liujbjl@linux.vnet.ibm.com>
Reviewed-by: QingFeng Hao <haoqf@linux.vnet.ibm.com>
Reviewed-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 hw/char/terminal3270.c | 37 ++++++++++++++++++++++++++++++++-----
 1 file changed, 32 insertions(+), 5 deletions(-)

diff --git a/hw/char/terminal3270.c b/hw/char/terminal3270.c
index 450608e3c3..58bcc4be15 100644
--- a/hw/char/terminal3270.c
+++ b/hw/char/terminal3270.c
@@ -32,6 +32,7 @@ typedef struct Terminal3270 {
     int in_len;
     int out_len;
     bool handshake_done;
+    guint timer_tag;
 } Terminal3270;
 
 #define TYPE_TERMINAL_3270 "x-terminal3270"
@@ -60,6 +61,19 @@ static void TN3270_handshake_done(Terminal3270 *t)
 }
 
 /*
+ * Called when the interval is timeout to detect
+ * if the client is still alive by Timing Mark.
+ */
+static gboolean send_timing_mark_cb(gpointer opaque)
+{
+    Terminal3270 *t = opaque;
+    const uint8_t timing[] = {0xff, 0xfd, 0x06};
+
+    qemu_chr_fe_write_all(&t->chr, timing, sizeof(timing));
+    return true;
+}
+
+/*
  * Receive inbound data from socket.
  * For data given to guest, drop the data boundary IAC, IAC_EOR.
  * TODO:
@@ -77,6 +91,12 @@ static void terminal_read(void *opaque, const uint8_t *buf, int size)
 
     assert(size <= (INPUT_BUFFER_SIZE - t->in_len));
 
+    if (t->timer_tag) {
+        g_source_remove(t->timer_tag);
+        t->timer_tag = 0;
+    }
+    t->timer_tag = g_timeout_add_seconds(600, send_timing_mark_cb, t);
+
     memcpy(&t->inv[t->in_len], buf, size);
     t->in_len += size;
     if (t->in_len < 2) {
@@ -127,6 +147,10 @@ static void chr_event(void *opaque, int event)
     t->in_len = 0;
     t->out_len = 0;
     t->handshake_done = false;
+    if (t->timer_tag) {
+        g_source_remove(t->timer_tag);
+        t->timer_tag = 0;
+    }
 
     switch (event) {
     case CHR_EVENT_OPENED:
@@ -135,6 +159,7 @@ static void chr_event(void *opaque, int event)
          * char-socket.c. Once qemu receives the terminal-type of the
          * client, mark handshake done and trigger everything rolling again.
          */
+        t->timer_tag = g_timeout_add_seconds(600, send_timing_mark_cb, t);
         break;
     case CHR_EVENT_CLOSED:
         sch->curr_status.scsw.dstat = SCSW_DSTAT_DEVICE_END;
@@ -206,11 +231,13 @@ static int write_payload_3270(EmulatedCcw3270Device *dev, uint8_t cmd,
     assert(count <= (OUTPUT_BUFFER_SIZE - 3) / 2);
 
     if (!t->handshake_done) {
-        /*
-         * Before having finished 3270 negotiation,
-         * sending outbound data is prohibited.
-         */
-        return 0;
+        if (!(t->outv[0] == IAC && t->outv[1] != IAC)) {
+            /*
+             * Before having finished 3270 negotiation,
+             * sending outbound data except protocol options is prohibited.
+             */
+            return 0;
+        }
     }
     if (!qemu_chr_fe_get_driver(&t->chr)) {
         /* We just say we consumed all data if there's no backend. */
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PATCH v2 for-2.10 8/8] s390x/3270: Mark non-migratable and enable the device
  2017-04-07 11:18 [Qemu-devel] [PATCH v2 for-2.10 0/8] s390x: Basic support for 3270 devices Cornelia Huck
                   ` (6 preceding siblings ...)
  2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 7/8] s390x/3270: Detect for continued presence of a 3270 client Cornelia Huck
@ 2017-04-07 11:18 ` Cornelia Huck
  7 siblings, 0 replies; 15+ messages in thread
From: Cornelia Huck @ 2017-04-07 11:18 UTC (permalink / raw)
  To: qemu-devel
  Cc: borntraeger, agraf, pbonzini, marcandre.lureau, Jing Liu,
	Yang Chen, Cornelia Huck

From: Jing Liu <liujbjl@linux.vnet.ibm.com>

Mark 3270 as non-migratable for the experimental stage. Enable
the 3270 device so that we can use x3270 client to operate the guest.

Run qemu with the arguments:
    -chardev socket,id=char3270_0,host=0.0.0.0,port=23,nowait,server,tn3270 \
    -device x-terminal3270,chardev=char3270_0,devno=fe.0.000a,id=terminal3270_0 \

There are some restrictions for the first stage: We don't support SSL
connections, multiple client connections and client resizing. Only
tested with the x3270 client.

Signed-off-by: Jing Liu <liujbjl@linux.vnet.ibm.com>
Signed-off-by: Yang Chen <bjcyang@linux.vnet.ibm.com>
Reviewed-by: QingFeng Hao <haoqf@linux.vnet.ibm.com>
Reviewed-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 default-configs/s390x-softmmu.mak | 1 +
 hw/char/Makefile.objs             | 1 +
 hw/char/terminal3270.c            | 6 ++++++
 3 files changed, 8 insertions(+)

diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak
index 36e15de336..9615a48f80 100644
--- a/default-configs/s390x-softmmu.mak
+++ b/default-configs/s390x-softmmu.mak
@@ -2,6 +2,7 @@ CONFIG_PCI=y
 CONFIG_VIRTIO_PCI=y
 CONFIG_VIRTIO=y
 CONFIG_SCLPCONSOLE=y
+CONFIG_TERMINAL3270=y
 CONFIG_S390_FLIC=y
 CONFIG_S390_FLIC_KVM=$(CONFIG_KVM)
 CONFIG_WDT_DIAG288=y
diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs
index 725fdc46f4..55fcb68fd2 100644
--- a/hw/char/Makefile.objs
+++ b/hw/char/Makefile.objs
@@ -29,3 +29,4 @@ common-obj-$(CONFIG_MILKYMIST) += milkymist-uart.o
 common-obj-$(CONFIG_SCLPCONSOLE) += sclpconsole.o sclpconsole-lm.o
 
 obj-$(CONFIG_VIRTIO) += virtio-serial-bus.o
+obj-$(CONFIG_TERMINAL3270) += terminal3270.o
diff --git a/hw/char/terminal3270.c b/hw/char/terminal3270.c
index 58bcc4be15..b2dda01baa 100644
--- a/hw/char/terminal3270.c
+++ b/hw/char/terminal3270.c
@@ -260,12 +260,18 @@ static Property terminal_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
+static const VMStateDescription terminal3270_vmstate = {
+    .name = TYPE_TERMINAL_3270,
+    .unmigratable = 1,
+};
+
 static void terminal_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     EmulatedCcw3270Class *ck = EMULATED_CCW_3270_CLASS(klass);
 
     dc->props = terminal_properties;
+    dc->vmsd = &terminal3270_vmstate;
     ck->init = terminal_init;
     ck->read_payload_3270 = read_payload_3270;
     ck->write_payload_3270 = write_payload_3270;
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [Qemu-devel] [PATCH v2 for-2.10 1/8] chardev: Basic support for TN3270
  2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 1/8] chardev: Basic support for TN3270 Cornelia Huck
@ 2017-04-07 13:58   ` Eric Blake
  2017-04-10 12:16     ` Cornelia Huck
  2017-04-24 10:38   ` Cornelia Huck
  2017-04-28 14:17   ` Marc-André Lureau
  2 siblings, 1 reply; 15+ messages in thread
From: Eric Blake @ 2017-04-07 13:58 UTC (permalink / raw)
  To: Cornelia Huck, qemu-devel
  Cc: Jing Liu, agraf, borntraeger, pbonzini, marcandre.lureau, Yang Chen

[-- Attachment #1: Type: text/plain, Size: 2282 bytes --]

On 04/07/2017 06:18 AM, Cornelia Huck wrote:
> From: Jing Liu <liujbjl@linux.vnet.ibm.com>
> 
> This introduces basic support for TN3270, which needs to negotiate
> three Telnet options during handshake:
>   - End of Record
>   - Binary Transmission
>   - Terminal-Type
> 
> As a basic implementation, this simply ignores NOP and Interrupt
> Process(IP) commands. More work should be done for them later.
> 
> For more details, please refer to RFC 854 and 1576.
> 
> Signed-off-by: Jing Liu <liujbjl@linux.vnet.ibm.com>
> Signed-off-by: Yang Chen <bjcyang@linux.vnet.ibm.com>
> Reviewed-by: QingFeng Hao <haoqf@linux.vnet.ibm.com>
> Acked-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
> ---

> +++ b/qapi-schema.json
> @@ -4874,6 +4874,8 @@
>  # @nodelay: set TCP_NODELAY socket option (default: false)
>  # @telnet: enable telnet protocol on server
>  #          sockets (default: false)
> +# @tn3270: enable tn3270 protocol on server
> +#          sockets (default: false) (Since: 2.10)
>  # @reconnect: For a client socket, if a socket is disconnected,
>  #          then attempt a reconnect after the given number of seconds.
>  #          Setting this to zero disables this function. (default: 0)
> @@ -4887,6 +4889,7 @@
>                                       '*wait'      : 'bool',
>                                       '*nodelay'   : 'bool',
>                                       '*telnet'    : 'bool',
> +                                     '*tn3270'    : 'bool',
>                                       '*reconnect' : 'int' },
>    'base': 'ChardevCommon' }

I almost wonder if we should make this a flat union, so that members
that only make sense with the server side (such as tn3270) or with the
client side (reconnect) can only be present when that branch of the
union is taken.  But that may break back-compat if we have existing code
that silently ignores a member that makes no sense, and we start
forcefully warning about the member being present.  At any rate, making
such a change is not a prerequisite for this series.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Qemu-devel] [PATCH v2 for-2.10 1/8] chardev: Basic support for TN3270
  2017-04-07 13:58   ` Eric Blake
@ 2017-04-10 12:16     ` Cornelia Huck
  0 siblings, 0 replies; 15+ messages in thread
From: Cornelia Huck @ 2017-04-10 12:16 UTC (permalink / raw)
  To: Eric Blake
  Cc: qemu-devel, Jing Liu, agraf, borntraeger, pbonzini,
	marcandre.lureau, Yang Chen

On Fri, 7 Apr 2017 08:58:15 -0500
Eric Blake <eblake@redhat.com> wrote:

> On 04/07/2017 06:18 AM, Cornelia Huck wrote:
> > From: Jing Liu <liujbjl@linux.vnet.ibm.com>
> > 
> > This introduces basic support for TN3270, which needs to negotiate
> > three Telnet options during handshake:
> >   - End of Record
> >   - Binary Transmission
> >   - Terminal-Type
> > 
> > As a basic implementation, this simply ignores NOP and Interrupt
> > Process(IP) commands. More work should be done for them later.
> > 
> > For more details, please refer to RFC 854 and 1576.
> > 
> > Signed-off-by: Jing Liu <liujbjl@linux.vnet.ibm.com>
> > Signed-off-by: Yang Chen <bjcyang@linux.vnet.ibm.com>
> > Reviewed-by: QingFeng Hao <haoqf@linux.vnet.ibm.com>
> > Acked-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
> > Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
> > ---
> 
> > +++ b/qapi-schema.json
> > @@ -4874,6 +4874,8 @@
> >  # @nodelay: set TCP_NODELAY socket option (default: false)
> >  # @telnet: enable telnet protocol on server
> >  #          sockets (default: false)
> > +# @tn3270: enable tn3270 protocol on server
> > +#          sockets (default: false) (Since: 2.10)
> >  # @reconnect: For a client socket, if a socket is disconnected,
> >  #          then attempt a reconnect after the given number of seconds.
> >  #          Setting this to zero disables this function. (default: 0)
> > @@ -4887,6 +4889,7 @@
> >                                       '*wait'      : 'bool',
> >                                       '*nodelay'   : 'bool',
> >                                       '*telnet'    : 'bool',
> > +                                     '*tn3270'    : 'bool',
> >                                       '*reconnect' : 'int' },
> >    'base': 'ChardevCommon' }
> 
> I almost wonder if we should make this a flat union, so that members
> that only make sense with the server side (such as tn3270) or with the
> client side (reconnect) can only be present when that branch of the
> union is taken.  But that may break back-compat if we have existing code
> that silently ignores a member that makes no sense, and we start
> forcefully warning about the member being present.  

The existing mix of server and client side members is a bit
unfortunate, but I'm not sure it's worth spending effort on this.
Anyway, I'd defer that to the chardev maintainers :)

> At any rate, making
> such a change is not a prerequisite for this series.

Would be nice if this is fine as-is.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Qemu-devel] [PATCH v2 for-2.10 1/8] chardev: Basic support for TN3270
  2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 1/8] chardev: Basic support for TN3270 Cornelia Huck
  2017-04-07 13:58   ` Eric Blake
@ 2017-04-24 10:38   ` Cornelia Huck
  2017-04-28 14:17   ` Marc-André Lureau
  2 siblings, 0 replies; 15+ messages in thread
From: Cornelia Huck @ 2017-04-24 10:38 UTC (permalink / raw)
  To: qemu-devel
  Cc: borntraeger, agraf, pbonzini, marcandre.lureau, Jing Liu, Yang Chen

On Fri,  7 Apr 2017 13:18:44 +0200
Cornelia Huck <cornelia.huck@de.ibm.com> wrote:

> From: Jing Liu <liujbjl@linux.vnet.ibm.com>
> 
> This introduces basic support for TN3270, which needs to negotiate
> three Telnet options during handshake:
>   - End of Record
>   - Binary Transmission
>   - Terminal-Type
> 
> As a basic implementation, this simply ignores NOP and Interrupt
> Process(IP) commands. More work should be done for them later.
> 
> For more details, please refer to RFC 854 and 1576.
> 
> Signed-off-by: Jing Liu <liujbjl@linux.vnet.ibm.com>
> Signed-off-by: Yang Chen <bjcyang@linux.vnet.ibm.com>
> Reviewed-by: QingFeng Hao <haoqf@linux.vnet.ibm.com>
> Acked-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
> ---
>  chardev/char-socket.c | 76 +++++++++++++++++++++++++++++++++++++--------------
>  chardev/char.c        | 11 ++++++--
>  include/sysemu/char.h |  8 ++++++
>  qapi-schema.json      |  3 ++
>  4 files changed, 76 insertions(+), 22 deletions(-)

ping for some acks for the telnet changes

> 
> diff --git a/chardev/char-socket.c b/chardev/char-socket.c
> index 36ab0d633a..175fb8c3ec 100644
> --- a/chardev/char-socket.c
> +++ b/chardev/char-socket.c
> @@ -55,6 +55,7 @@ typedef struct {
>      SocketAddress *addr;
>      bool is_listen;
>      bool is_telnet;
> +    bool is_tn3270;
> 
>      guint reconnect_timer;
>      int64_t reconnect_time;
> @@ -141,19 +142,25 @@ static int tcp_chr_read_poll(void *opaque)
>      return s->max_size;
>  }
> 
> -#define IAC 255
> -#define IAC_BREAK 243
>  static void tcp_chr_process_IAC_bytes(Chardev *chr,
>                                        SocketChardev *s,
>                                        uint8_t *buf, int *size)
>  {
> -    /* Handle any telnet client's basic IAC options to satisfy char by
> -     * char mode with no echo.  All IAC options will be removed from
> -     * the buf and the do_telnetopt variable will be used to track the
> -     * state of the width of the IAC information.
> +    /* Handle any telnet or tn3270 client's basic IAC options.
> +     * For telnet options, it satisfies char by char mode with no echo.
> +     * For tn3270 options, it satisfies binary mode with EOR.
> +     * All IAC options will be removed from the buf and the do_opt
> +     * pointer will be used to track the state of the width of the
> +     * IAC information.
>       *
> -     * IAC commands come in sets of 3 bytes with the exception of the
> -     * "IAC BREAK" command and the double IAC.
> +     * RFC854: "All TELNET commands consist of at least a two byte sequence.
> +     * The commands dealing with option negotiation are three byte sequences,
> +     * the third byte being the code for the option referenced."
> +     * "IAC BREAK", "IAC IP", "IAC NOP" and the double IAC are two bytes.
> +     * "IAC SB", "IAC SE" and "IAC EOR" are saved to split up data boundary
> +     * for tn3270.
> +     * NOP, Break and Interrupt Process(IP) might be encountered during a TN3270
> +     * session, and NOP and IP need to be done later.
>       */
> 
>      int i;
> @@ -174,6 +181,18 @@ static void tcp_chr_process_IAC_bytes(Chardev *chr,
>                      /* Handle IAC break commands by sending a serial break */
>                      qemu_chr_be_event(chr, CHR_EVENT_BREAK);
>                      s->do_telnetopt++;
> +                } else if (s->is_tn3270 && ((unsigned char)buf[i] == IAC_EOR
> +                           || (unsigned char)buf[i] == IAC_SB
> +                           || (unsigned char)buf[i] == IAC_SE)
> +                           && s->do_telnetopt == 2) {
> +                    buf[j++] = IAC;
> +                    buf[j++] = buf[i];
> +                    s->do_telnetopt++;
> +                } else if (s->is_tn3270 && ((unsigned char)buf[i] == IAC_IP
> +                           || (unsigned char)buf[i] == IAC_NOP)
> +                           && s->do_telnetopt == 2) {
> +                    /* TODO: IP and NOP need to be implemented later. */
> +                    s->do_telnetopt++;
>                  }
>                  s->do_telnetopt++;
>              }
> @@ -512,7 +531,7 @@ static void tcp_chr_update_read_handler(Chardev *chr,
> 
>  typedef struct {
>      Chardev *chr;
> -    char buf[12];
> +    char buf[21];
>      size_t buflen;
>  } TCPChardevTelnetInit;
> 
> @@ -550,9 +569,6 @@ static void tcp_chr_telnet_init(Chardev *chr)
>      TCPChardevTelnetInit *init = g_new0(TCPChardevTelnetInit, 1);
>      size_t n = 0;
> 
> -    init->chr = chr;
> -    init->buflen = 12;
> -
>  #define IACSET(x, a, b, c)                      \
>      do {                                        \
>          x[n++] = a;                             \
> @@ -560,12 +576,26 @@ static void tcp_chr_telnet_init(Chardev *chr)
>          x[n++] = c;                             \
>      } while (0)
> 
> -    /* Prep the telnet negotion to put telnet in binary,
> -     * no echo, single char mode */
> -    IACSET(init->buf, 0xff, 0xfb, 0x01);  /* IAC WILL ECHO */
> -    IACSET(init->buf, 0xff, 0xfb, 0x03);  /* IAC WILL Suppress go ahead */
> -    IACSET(init->buf, 0xff, 0xfb, 0x00);  /* IAC WILL Binary */
> -    IACSET(init->buf, 0xff, 0xfd, 0x00);  /* IAC DO Binary */
> +    init->chr = chr;
> +    if (!s->is_tn3270) {
> +        init->buflen = 12;
> +        /* Prep the telnet negotion to put telnet in binary,
> +         * no echo, single char mode */
> +        IACSET(init->buf, 0xff, 0xfb, 0x01);  /* IAC WILL ECHO */
> +        IACSET(init->buf, 0xff, 0xfb, 0x03);  /* IAC WILL Suppress go ahead */
> +        IACSET(init->buf, 0xff, 0xfb, 0x00);  /* IAC WILL Binary */
> +        IACSET(init->buf, 0xff, 0xfd, 0x00);  /* IAC DO Binary */
> +    } else {
> +        init->buflen = 21;
> +        /* Prep the TN3270 negotion based on RFC1576 */
> +        IACSET(init->buf, 0xff, 0xfd, 0x19);  /* IAC DO EOR */
> +        IACSET(init->buf, 0xff, 0xfb, 0x19);  /* IAC WILL EOR */
> +        IACSET(init->buf, 0xff, 0xfd, 0x00);  /* IAC DO BINARY */
> +        IACSET(init->buf, 0xff, 0xfb, 0x00);  /* IAC WILL BINARY */
> +        IACSET(init->buf, 0xff, 0xfd, 0x18);  /* IAC DO TERMINAL TYPE */
> +        IACSET(init->buf, 0xff, 0xfa, 0x18);  /* IAC SB TERMINAL TYPE */
> +        IACSET(init->buf, 0x01, 0xff, 0xf0);  /* SEND IAC SE */
> +    }
> 
>  #undef IACSET
> 
> @@ -585,7 +615,8 @@ static void tcp_chr_tls_handshake(QIOTask *task,
>      if (qio_task_propagate_error(task, NULL)) {
>          tcp_chr_disconnect(chr);
>      } else {
> -        if (s->do_telnetopt) {
> +        /* tn3270 does not support TLS yet */
> +        if (s->do_telnetopt && !s->is_tn3270) {
>              tcp_chr_telnet_init(chr);
>          } else {
>              tcp_chr_connect(chr);
> @@ -824,12 +855,14 @@ static void qmp_chardev_open_socket(Chardev *chr,
>      bool do_nodelay     = sock->has_nodelay ? sock->nodelay : false;
>      bool is_listen      = sock->has_server  ? sock->server  : true;
>      bool is_telnet      = sock->has_telnet  ? sock->telnet  : false;
> +    bool is_tn3270      = sock->has_tn3270  ? sock->tn3270  : false;
>      bool is_waitconnect = sock->has_wait    ? sock->wait    : false;
>      int64_t reconnect   = sock->has_reconnect ? sock->reconnect : 0;
>      QIOChannelSocket *sioc = NULL;
> 
>      s->is_listen = is_listen;
>      s->is_telnet = is_telnet;
> +    s->is_tn3270 = is_tn3270;
>      s->do_nodelay = do_nodelay;
>      if (sock->tls_creds) {
>          Object *creds;
> @@ -879,7 +912,7 @@ static void qmp_chardev_open_socket(Chardev *chr,
>                                           addr, is_listen, is_telnet);
> 
>      if (is_listen) {
> -        if (is_telnet) {
> +        if (is_telnet || is_tn3270) {
>              s->do_telnetopt = 1;
>          }
>      } else if (reconnect > 0) {
> @@ -933,6 +966,7 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
>      bool is_listen      = qemu_opt_get_bool(opts, "server", false);
>      bool is_waitconnect = is_listen && qemu_opt_get_bool(opts, "wait", true);
>      bool is_telnet      = qemu_opt_get_bool(opts, "telnet", false);
> +    bool is_tn3270      = qemu_opt_get_bool(opts, "tn3270", false);
>      bool do_nodelay     = !qemu_opt_get_bool(opts, "delay", true);
>      int64_t reconnect   = qemu_opt_get_number(opts, "reconnect", 0);
>      const char *path = qemu_opt_get(opts, "path");
> @@ -968,6 +1002,8 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
>      sock->server = is_listen;
>      sock->has_telnet = true;
>      sock->telnet = is_telnet;
> +    sock->has_tn3270 = true;
> +    sock->tn3270 = is_tn3270;
>      sock->has_wait = true;
>      sock->wait = is_waitconnect;
>      sock->has_reconnect = true;
> diff --git a/chardev/char.c b/chardev/char.c
> index 3df116350b..309734f2b7 100644
> --- a/chardev/char.c
> +++ b/chardev/char.c
> @@ -696,7 +696,8 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
>          return opts;
>      }
>      if (strstart(filename, "tcp:", &p) ||
> -        strstart(filename, "telnet:", &p)) {
> +        strstart(filename, "telnet:", &p) ||
> +        strstart(filename, "tn3270:", &p)) {
>          if (sscanf(p, "%64[^:]:%32[^,]%n", host, port, &pos) < 2) {
>              host[0] = 0;
>              if (sscanf(p, ":%32[^,]%n", port, &pos) < 1)
> @@ -712,8 +713,11 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
>                  goto fail;
>              }
>          }
> -        if (strstart(filename, "telnet:", &p))
> +        if (strstart(filename, "telnet:", &p)) {
>              qemu_opt_set(opts, "telnet", "on", &error_abort);
> +        } else if (strstart(filename, "tn3270:", &p)) {
> +            qemu_opt_set(opts, "tn3270", "on", &error_abort);
> +        }
>          return opts;
>      }
>      if (strstart(filename, "udp:", &p)) {
> @@ -1177,6 +1181,9 @@ QemuOptsList qemu_chardev_opts = {
>              .name = "telnet",
>              .type = QEMU_OPT_BOOL,
>          },{
> +            .name = "tn3270",
> +            .type = QEMU_OPT_BOOL,
> +        },{
>              .name = "tls-creds",
>              .type = QEMU_OPT_STRING,
>          },{
> diff --git a/include/sysemu/char.h b/include/sysemu/char.h
> index 450881d42c..f6d5cd0c9b 100644
> --- a/include/sysemu/char.h
> +++ b/include/sysemu/char.h
> @@ -7,6 +7,14 @@
>  #include "qemu/bitmap.h"
>  #include "qom/object.h"
> 
> +#define IAC_EOR 239
> +#define IAC_SE 240
> +#define IAC_NOP 241
> +#define IAC_BREAK 243
> +#define IAC_IP 244
> +#define IAC_SB 250
> +#define IAC 255
> +
>  /* character device */
> 
>  typedef enum {
> diff --git a/qapi-schema.json b/qapi-schema.json
> index 250e4dc49b..f0302958ce 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -4874,6 +4874,8 @@
>  # @nodelay: set TCP_NODELAY socket option (default: false)
>  # @telnet: enable telnet protocol on server
>  #          sockets (default: false)
> +# @tn3270: enable tn3270 protocol on server
> +#          sockets (default: false) (Since: 2.10)
>  # @reconnect: For a client socket, if a socket is disconnected,
>  #          then attempt a reconnect after the given number of seconds.
>  #          Setting this to zero disables this function. (default: 0)
> @@ -4887,6 +4889,7 @@
>                                       '*wait'      : 'bool',
>                                       '*nodelay'   : 'bool',
>                                       '*telnet'    : 'bool',
> +                                     '*tn3270'    : 'bool',
>                                       '*reconnect' : 'int' },
>    'base': 'ChardevCommon' }
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Qemu-devel] [PATCH v2 for-2.10 1/8] chardev: Basic support for TN3270
  2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 1/8] chardev: Basic support for TN3270 Cornelia Huck
  2017-04-07 13:58   ` Eric Blake
  2017-04-24 10:38   ` Cornelia Huck
@ 2017-04-28 14:17   ` Marc-André Lureau
  2017-05-03 11:31     ` Cornelia Huck
  2 siblings, 1 reply; 15+ messages in thread
From: Marc-André Lureau @ 2017-04-28 14:17 UTC (permalink / raw)
  To: Cornelia Huck, qemu-devel
  Cc: Jing Liu, agraf, borntraeger, pbonzini, Yang Chen

Hi

On Fri, Apr 7, 2017 at 3:19 PM Cornelia Huck <cornelia.huck@de.ibm.com>
wrote:

> From: Jing Liu <liujbjl@linux.vnet.ibm.com>
>
> This introduces basic support for TN3270, which needs to negotiate
> three Telnet options during handshake:
>   - End of Record
>   - Binary Transmission
>   - Terminal-Type
>
> As a basic implementation, this simply ignores NOP and Interrupt
> Process(IP) commands. More work should be done for them later.
>
> For more details, please refer to RFC 854 and 1576.
>
Signed-off-by: Jing Liu <liujbjl@linux.vnet.ibm.com>
> Signed-off-by: Yang Chen <bjcyang@linux.vnet.ibm.com>
> Reviewed-by: QingFeng Hao <haoqf@linux.vnet.ibm.com>
> Acked-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
> ---
>  chardev/char-socket.c | 76
> +++++++++++++++++++++++++++++++++++++--------------
>  chardev/char.c        | 11 ++++++--
>  include/sysemu/char.h |  8 ++++++
>  qapi-schema.json      |  3 ++
>  4 files changed, 76 insertions(+), 22 deletions(-)
>
> diff --git a/chardev/char-socket.c b/chardev/char-socket.c
> index 36ab0d633a..175fb8c3ec 100644
> --- a/chardev/char-socket.c
> +++ b/chardev/char-socket.c
> @@ -55,6 +55,7 @@ typedef struct {
>      SocketAddress *addr;
>      bool is_listen;
>      bool is_telnet;
> +    bool is_tn3270;
>
>      guint reconnect_timer;
>      int64_t reconnect_time;
> @@ -141,19 +142,25 @@ static int tcp_chr_read_poll(void *opaque)
>      return s->max_size;
>  }
>
> -#define IAC 255
> -#define IAC_BREAK 243
>  static void tcp_chr_process_IAC_bytes(Chardev *chr,
>                                        SocketChardev *s,
>                                        uint8_t *buf, int *size)
>  {
> -    /* Handle any telnet client's basic IAC options to satisfy char by
> -     * char mode with no echo.  All IAC options will be removed from
> -     * the buf and the do_telnetopt variable will be used to track the
> -     * state of the width of the IAC information.
> +    /* Handle any telnet or tn3270 client's basic IAC options.
> +     * For telnet options, it satisfies char by char mode with no echo.
> +     * For tn3270 options, it satisfies binary mode with EOR.
> +     * All IAC options will be removed from the buf and the do_opt
> +     * pointer will be used to track the state of the width of the
> +     * IAC information.
>       *
> -     * IAC commands come in sets of 3 bytes with the exception of the
> -     * "IAC BREAK" command and the double IAC.
> +     * RFC854: "All TELNET commands consist of at least a two byte
> sequence.
> +     * The commands dealing with option negotiation are three byte
> sequences,
> +     * the third byte being the code for the option referenced."
> +     * "IAC BREAK", "IAC IP", "IAC NOP" and the double IAC are two bytes.
> +     * "IAC SB", "IAC SE" and "IAC EOR" are saved to split up data
> boundary
> +     * for tn3270.
> +     * NOP, Break and Interrupt Process(IP) might be encountered during a
> TN3270
> +     * session, and NOP and IP need to be done later.
>       */
>
>      int i;
> @@ -174,6 +181,18 @@ static void tcp_chr_process_IAC_bytes(Chardev *chr,
>                      /* Handle IAC break commands by sending a serial
> break */
>                      qemu_chr_be_event(chr, CHR_EVENT_BREAK);
>                      s->do_telnetopt++;
> +                } else if (s->is_tn3270 && ((unsigned char)buf[i] ==
> IAC_EOR
> +                           || (unsigned char)buf[i] == IAC_SB
> +                           || (unsigned char)buf[i] == IAC_SE)
> +                           && s->do_telnetopt == 2) {
> +                    buf[j++] = IAC;
> +                    buf[j++] = buf[i];
> +                    s->do_telnetopt++;
> +                } else if (s->is_tn3270 && ((unsigned char)buf[i] ==
> IAC_IP
> +                           || (unsigned char)buf[i] == IAC_NOP)
> +                           && s->do_telnetopt == 2) {
> +                    /* TODO: IP and NOP need to be implemented later. */
> +                    s->do_telnetopt++;
>                  }
>                  s->do_telnetopt++;
>              }
> @@ -512,7 +531,7 @@ static void tcp_chr_update_read_handler(Chardev *chr,
>
>  typedef struct {
>      Chardev *chr;
> -    char buf[12];
> +    char buf[21];
>      size_t buflen;
>  } TCPChardevTelnetInit;
>
> @@ -550,9 +569,6 @@ static void tcp_chr_telnet_init(Chardev *chr)
>      TCPChardevTelnetInit *init = g_new0(TCPChardevTelnetInit, 1);
>      size_t n = 0;
>
> -    init->chr = chr;
> -    init->buflen = 12;
> -
>  #define IACSET(x, a, b, c)                      \
>      do {                                        \
>          x[n++] = a;                             \
> @@ -560,12 +576,26 @@ static void tcp_chr_telnet_init(Chardev *chr)
>          x[n++] = c;                             \
>      } while (0)
>
> -    /* Prep the telnet negotion to put telnet in binary,
> -     * no echo, single char mode */
> -    IACSET(init->buf, 0xff, 0xfb, 0x01);  /* IAC WILL ECHO */
> -    IACSET(init->buf, 0xff, 0xfb, 0x03);  /* IAC WILL Suppress go ahead */
> -    IACSET(init->buf, 0xff, 0xfb, 0x00);  /* IAC WILL Binary */
> -    IACSET(init->buf, 0xff, 0xfd, 0x00);  /* IAC DO Binary */
> +    init->chr = chr;
> +    if (!s->is_tn3270) {
> +        init->buflen = 12;
> +        /* Prep the telnet negotion to put telnet in binary,
> +         * no echo, single char mode */
> +        IACSET(init->buf, 0xff, 0xfb, 0x01);  /* IAC WILL ECHO */
> +        IACSET(init->buf, 0xff, 0xfb, 0x03);  /* IAC WILL Suppress go
> ahead */
> +        IACSET(init->buf, 0xff, 0xfb, 0x00);  /* IAC WILL Binary */
> +        IACSET(init->buf, 0xff, 0xfd, 0x00);  /* IAC DO Binary */
> +    } else {
> +        init->buflen = 21;
> +        /* Prep the TN3270 negotion based on RFC1576 */
> +        IACSET(init->buf, 0xff, 0xfd, 0x19);  /* IAC DO EOR */
> +        IACSET(init->buf, 0xff, 0xfb, 0x19);  /* IAC WILL EOR */
> +        IACSET(init->buf, 0xff, 0xfd, 0x00);  /* IAC DO BINARY */
> +        IACSET(init->buf, 0xff, 0xfb, 0x00);  /* IAC WILL BINARY */
> +        IACSET(init->buf, 0xff, 0xfd, 0x18);  /* IAC DO TERMINAL TYPE */
> +        IACSET(init->buf, 0xff, 0xfa, 0x18);  /* IAC SB TERMINAL TYPE */
> +        IACSET(init->buf, 0x01, 0xff, 0xf0);  /* SEND IAC SE */
> +    }
>
>  #undef IACSET
>
> @@ -585,7 +615,8 @@ static void tcp_chr_tls_handshake(QIOTask *task,
>      if (qio_task_propagate_error(task, NULL)) {
>          tcp_chr_disconnect(chr);
>      } else {
> -        if (s->do_telnetopt) {
> +        /* tn3270 does not support TLS yet */
> +        if (s->do_telnetopt && !s->is_tn3270) {
>              tcp_chr_telnet_init(chr);
>          } else {
>              tcp_chr_connect(chr);
> @@ -824,12 +855,14 @@ static void qmp_chardev_open_socket(Chardev *chr,
>      bool do_nodelay     = sock->has_nodelay ? sock->nodelay : false;
>      bool is_listen      = sock->has_server  ? sock->server  : true;
>      bool is_telnet      = sock->has_telnet  ? sock->telnet  : false;
> +    bool is_tn3270      = sock->has_tn3270  ? sock->tn3270  : false;
>      bool is_waitconnect = sock->has_wait    ? sock->wait    : false;
>      int64_t reconnect   = sock->has_reconnect ? sock->reconnect : 0;
>      QIOChannelSocket *sioc = NULL;
>
>      s->is_listen = is_listen;
>      s->is_telnet = is_telnet;
> +    s->is_tn3270 = is_tn3270;
>      s->do_nodelay = do_nodelay;
>      if (sock->tls_creds) {
>          Object *creds;
> @@ -879,7 +912,7 @@ static void qmp_chardev_open_socket(Chardev *chr,
>                                           addr, is_listen, is_telnet);
>
>      if (is_listen) {
> -        if (is_telnet) {
> +        if (is_telnet || is_tn3270) {
>              s->do_telnetopt = 1;
>          }
>      } else if (reconnect > 0) {
> @@ -933,6 +966,7 @@ static void qemu_chr_parse_socket(QemuOpts *opts,
> ChardevBackend *backend,
>      bool is_listen      = qemu_opt_get_bool(opts, "server", false);
>      bool is_waitconnect = is_listen && qemu_opt_get_bool(opts, "wait",
> true);
>      bool is_telnet      = qemu_opt_get_bool(opts, "telnet", false);
> +    bool is_tn3270      = qemu_opt_get_bool(opts, "tn3270", false);
>      bool do_nodelay     = !qemu_opt_get_bool(opts, "delay", true);
>      int64_t reconnect   = qemu_opt_get_number(opts, "reconnect", 0);
>      const char *path = qemu_opt_get(opts, "path");
> @@ -968,6 +1002,8 @@ static void qemu_chr_parse_socket(QemuOpts *opts,
> ChardevBackend *backend,
>      sock->server = is_listen;
>      sock->has_telnet = true;
>      sock->telnet = is_telnet;
> +    sock->has_tn3270 = true;
> +    sock->tn3270 = is_tn3270;
>      sock->has_wait = true;
>      sock->wait = is_waitconnect;
>      sock->has_reconnect = true;
> diff --git a/chardev/char.c b/chardev/char.c
> index 3df116350b..309734f2b7 100644
> --- a/chardev/char.c
> +++ b/chardev/char.c
> @@ -696,7 +696,8 @@ QemuOpts *qemu_chr_parse_compat(const char *label,
> const char *filename)
>          return opts;
>      }
>      if (strstart(filename, "tcp:", &p) ||
> -        strstart(filename, "telnet:", &p)) {
> +        strstart(filename, "telnet:", &p) ||
> +        strstart(filename, "tn3270:", &p)) {
>          if (sscanf(p, "%64[^:]:%32[^,]%n", host, port, &pos) < 2) {
>              host[0] = 0;
>              if (sscanf(p, ":%32[^,]%n", port, &pos) < 1)
> @@ -712,8 +713,11 @@ QemuOpts *qemu_chr_parse_compat(const char *label,
> const char *filename)
>                  goto fail;
>              }
>          }
> -        if (strstart(filename, "telnet:", &p))
> +        if (strstart(filename, "telnet:", &p)) {
>              qemu_opt_set(opts, "telnet", "on", &error_abort);
> +        } else if (strstart(filename, "tn3270:", &p)) {
> +            qemu_opt_set(opts, "tn3270", "on", &error_abort);
> +        }
>          return opts;
>      }
>      if (strstart(filename, "udp:", &p)) {
> @@ -1177,6 +1181,9 @@ QemuOptsList qemu_chardev_opts = {
>              .name = "telnet",
>              .type = QEMU_OPT_BOOL,
>          },{
> +            .name = "tn3270",
> +            .type = QEMU_OPT_BOOL,
> +        },{
>              .name = "tls-creds",
>              .type = QEMU_OPT_STRING,
>          },{
> diff --git a/include/sysemu/char.h b/include/sysemu/char.h
> index 450881d42c..f6d5cd0c9b 100644
> --- a/include/sysemu/char.h
> +++ b/include/sysemu/char.h
> @@ -7,6 +7,14 @@
>  #include "qemu/bitmap.h"
>  #include "qom/object.h"
>
> +#define IAC_EOR 239
> +#define IAC_SE 240
> +#define IAC_NOP 241
> +#define IAC_BREAK 243
> +#define IAC_IP 244
> +#define IAC_SB 250
> +#define IAC 255
> +
>

Those define are exposed because of a later patch.

(I have pending patches to have a char/char-socket.h and friends where this
should fit, but for now it's fine)

Patch looks good to me, basic testing done

 /* character device */
>
>  typedef enum {
> diff --git a/qapi-schema.json b/qapi-schema.json
> index 250e4dc49b..f0302958ce 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -4874,6 +4874,8 @@
>  # @nodelay: set TCP_NODELAY socket option (default: false)
>  # @telnet: enable telnet protocol on server
>  #          sockets (default: false)
> +# @tn3270: enable tn3270 protocol on server
> +#          sockets (default: false) (Since: 2.10)
>  # @reconnect: For a client socket, if a socket is disconnected,
>  #          then attempt a reconnect after the given number of seconds.
>  #          Setting this to zero disables this function. (default: 0)
> @@ -4887,6 +4889,7 @@
>                                       '*wait'      : 'bool',
>                                       '*nodelay'   : 'bool',
>                                       '*telnet'    : 'bool',
> +                                     '*tn3270'    : 'bool',
>                                       '*reconnect' : 'int' },
>    'base': 'ChardevCommon' }
>
> --
> 2.11.0
>
>
> --
Marc-André Lureau

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Qemu-devel] [PATCH v2 for-2.10 1/8] chardev: Basic support for TN3270
  2017-04-28 14:17   ` Marc-André Lureau
@ 2017-05-03 11:31     ` Cornelia Huck
  2017-05-03 11:59       ` Marc-André Lureau
  0 siblings, 1 reply; 15+ messages in thread
From: Cornelia Huck @ 2017-05-03 11:31 UTC (permalink / raw)
  To: Marc-André Lureau
  Cc: qemu-devel, Jing Liu, agraf, borntraeger, pbonzini, Yang Chen

On Fri, 28 Apr 2017 14:17:12 +0000
Marc-André Lureau <marcandre.lureau@gmail.com> wrote:

> Hi
> 
> On Fri, Apr 7, 2017 at 3:19 PM Cornelia Huck <cornelia.huck@de.ibm.com>
> wrote:
> 
> > From: Jing Liu <liujbjl@linux.vnet.ibm.com>
> >
> > This introduces basic support for TN3270, which needs to negotiate
> > three Telnet options during handshake:
> >   - End of Record
> >   - Binary Transmission
> >   - Terminal-Type
> >
> > As a basic implementation, this simply ignores NOP and Interrupt
> > Process(IP) commands. More work should be done for them later.
> >
> > For more details, please refer to RFC 854 and 1576.
> >
> Signed-off-by: Jing Liu <liujbjl@linux.vnet.ibm.com>
> > Signed-off-by: Yang Chen <bjcyang@linux.vnet.ibm.com>
> > Reviewed-by: QingFeng Hao <haoqf@linux.vnet.ibm.com>
> > Acked-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
> > Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
> > ---
> >  chardev/char-socket.c | 76
> > +++++++++++++++++++++++++++++++++++++--------------
> >  chardev/char.c        | 11 ++++++--
> >  include/sysemu/char.h |  8 ++++++
> >  qapi-schema.json      |  3 ++
> >  4 files changed, 76 insertions(+), 22 deletions(-)

> > diff --git a/include/sysemu/char.h b/include/sysemu/char.h
> > index 450881d42c..f6d5cd0c9b 100644
> > --- a/include/sysemu/char.h
> > +++ b/include/sysemu/char.h
> > @@ -7,6 +7,14 @@
> >  #include "qemu/bitmap.h"
> >  #include "qom/object.h"
> >
> > +#define IAC_EOR 239
> > +#define IAC_SE 240
> > +#define IAC_NOP 241
> > +#define IAC_BREAK 243
> > +#define IAC_IP 244
> > +#define IAC_SB 250
> > +#define IAC 255
> > +
> >
> 
> Those define are exposed because of a later patch.
> 
> (I have pending patches to have a char/char-socket.h and friends where this
> should fit, but for now it's fine)

OK. FWIW, I plan to send a pull req for 3270 this week.

> 
> Patch looks good to me, basic testing done

Cool, thanks. May I count that as an ack? :)

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Qemu-devel] [PATCH v2 for-2.10 1/8] chardev: Basic support for TN3270
  2017-05-03 11:31     ` Cornelia Huck
@ 2017-05-03 11:59       ` Marc-André Lureau
  0 siblings, 0 replies; 15+ messages in thread
From: Marc-André Lureau @ 2017-05-03 11:59 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: qemu-devel, Jing Liu, agraf, borntraeger, pbonzini, Yang Chen

On Wed, May 3, 2017 at 3:32 PM Cornelia Huck <cornelia.huck@de.ibm.com>
wrote:

> On Fri, 28 Apr 2017 14:17:12 +0000
> Marc-André Lureau <marcandre.lureau@gmail.com> wrote:
>
> > Hi
> >
> > On Fri, Apr 7, 2017 at 3:19 PM Cornelia Huck <cornelia.huck@de.ibm.com>
> > wrote:
> >
> > > From: Jing Liu <liujbjl@linux.vnet.ibm.com>
> > >
> > > This introduces basic support for TN3270, which needs to negotiate
> > > three Telnet options during handshake:
> > >   - End of Record
> > >   - Binary Transmission
> > >   - Terminal-Type
> > >
> > > As a basic implementation, this simply ignores NOP and Interrupt
> > > Process(IP) commands. More work should be done for them later.
> > >
> > > For more details, please refer to RFC 854 and 1576.
> > >
> > Signed-off-by: Jing Liu <liujbjl@linux.vnet.ibm.com>
> > > Signed-off-by: Yang Chen <bjcyang@linux.vnet.ibm.com>
> > > Reviewed-by: QingFeng Hao <haoqf@linux.vnet.ibm.com>
> > > Acked-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
> > > Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
> > > ---
> > >  chardev/char-socket.c | 76
> > > +++++++++++++++++++++++++++++++++++++--------------
> > >  chardev/char.c        | 11 ++++++--
> > >  include/sysemu/char.h |  8 ++++++
> > >  qapi-schema.json      |  3 ++
> > >  4 files changed, 76 insertions(+), 22 deletions(-)
>
> > > diff --git a/include/sysemu/char.h b/include/sysemu/char.h
> > > index 450881d42c..f6d5cd0c9b 100644
> > > --- a/include/sysemu/char.h
> > > +++ b/include/sysemu/char.h
> > > @@ -7,6 +7,14 @@
> > >  #include "qemu/bitmap.h"
> > >  #include "qom/object.h"
> > >
> > > +#define IAC_EOR 239
> > > +#define IAC_SE 240
> > > +#define IAC_NOP 241
> > > +#define IAC_BREAK 243
> > > +#define IAC_IP 244
> > > +#define IAC_SB 250
> > > +#define IAC 255
> > > +
> > >
> >
> > Those define are exposed because of a later patch.
> >
> > (I have pending patches to have a char/char-socket.h and friends where
> this
> > should fit, but for now it's fine)
>
> OK. FWIW, I plan to send a pull req for 3270 this week.
>
> >
> > Patch looks good to me, basic testing done
>
> Cool, thanks. May I count that as an ack? :)
>

yep
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
-- 
Marc-André Lureau

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2017-05-03 11:59 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-07 11:18 [Qemu-devel] [PATCH v2 for-2.10 0/8] s390x: Basic support for 3270 devices Cornelia Huck
2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 1/8] chardev: Basic support for TN3270 Cornelia Huck
2017-04-07 13:58   ` Eric Blake
2017-04-10 12:16     ` Cornelia Huck
2017-04-24 10:38   ` Cornelia Huck
2017-04-28 14:17   ` Marc-André Lureau
2017-05-03 11:31     ` Cornelia Huck
2017-05-03 11:59       ` Marc-André Lureau
2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 2/8] s390x/css: Add an algorithm to find a free chpid Cornelia Huck
2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 3/8] s390x/3270: Add abstract emulated ccw-attached 3270 device Cornelia Huck
2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 4/8] s390x/3270: Add emulated terminal3270 device Cornelia Huck
2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 5/8] s390x/3270: 3270 data stream handling Cornelia Huck
2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 6/8] s390x/3270: Add the TCP socket events handler for 3270 Cornelia Huck
2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 7/8] s390x/3270: Detect for continued presence of a 3270 client Cornelia Huck
2017-04-07 11:18 ` [Qemu-devel] [PATCH v2 for-2.10 8/8] s390x/3270: Mark non-migratable and enable the device Cornelia Huck

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.