1*2874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk) 51da177e4SLinus Torvalds */ 61da177e4SLinus Torvalds #include <linux/errno.h> 71da177e4SLinus Torvalds #include <linux/types.h> 81da177e4SLinus Torvalds #include <linux/socket.h> 91da177e4SLinus Torvalds #include <linux/in.h> 101da177e4SLinus Torvalds #include <linux/kernel.h> 111da177e4SLinus Torvalds #include <linux/timer.h> 121da177e4SLinus Torvalds #include <linux/string.h> 131da177e4SLinus Torvalds #include <linux/sockios.h> 141da177e4SLinus Torvalds #include <linux/net.h> 155a0e3ad6STejun Heo #include <linux/gfp.h> 161da177e4SLinus Torvalds #include <net/ax25.h> 171da177e4SLinus Torvalds #include <linux/inet.h> 181da177e4SLinus Torvalds #include <linux/netdevice.h> 191da177e4SLinus Torvalds #include <linux/skbuff.h> 201da177e4SLinus Torvalds #include <net/sock.h> 211da177e4SLinus Torvalds #include <linux/fcntl.h> 221da177e4SLinus Torvalds #include <linux/mm.h> 231da177e4SLinus Torvalds #include <linux/interrupt.h> 241da177e4SLinus Torvalds #include <net/rose.h> 251da177e4SLinus Torvalds 261da177e4SLinus Torvalds /* 271da177e4SLinus Torvalds * This procedure is passed a buffer descriptor for an iframe. It builds 281da177e4SLinus Torvalds * the rest of the control part of the frame and then writes it out. 291da177e4SLinus Torvalds */ 301da177e4SLinus Torvalds static void rose_send_iframe(struct sock *sk, struct sk_buff *skb) 311da177e4SLinus Torvalds { 321da177e4SLinus Torvalds struct rose_sock *rose = rose_sk(sk); 331da177e4SLinus Torvalds 341da177e4SLinus Torvalds if (skb == NULL) 351da177e4SLinus Torvalds return; 361da177e4SLinus Torvalds 371da177e4SLinus Torvalds skb->data[2] |= (rose->vr << 5) & 0xE0; 381da177e4SLinus Torvalds skb->data[2] |= (rose->vs << 1) & 0x0E; 391da177e4SLinus Torvalds 401da177e4SLinus Torvalds rose_start_idletimer(sk); 411da177e4SLinus Torvalds 421da177e4SLinus Torvalds rose_transmit_link(skb, rose->neighbour); 431da177e4SLinus Torvalds } 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds void rose_kick(struct sock *sk) 461da177e4SLinus Torvalds { 471da177e4SLinus Torvalds struct rose_sock *rose = rose_sk(sk); 481da177e4SLinus Torvalds struct sk_buff *skb, *skbn; 491da177e4SLinus Torvalds unsigned short start, end; 501da177e4SLinus Torvalds 511da177e4SLinus Torvalds if (rose->state != ROSE_STATE_3) 521da177e4SLinus Torvalds return; 531da177e4SLinus Torvalds 541da177e4SLinus Torvalds if (rose->condition & ROSE_COND_PEER_RX_BUSY) 551da177e4SLinus Torvalds return; 561da177e4SLinus Torvalds 571da177e4SLinus Torvalds if (!skb_peek(&sk->sk_write_queue)) 581da177e4SLinus Torvalds return; 591da177e4SLinus Torvalds 601da177e4SLinus Torvalds start = (skb_peek(&rose->ack_queue) == NULL) ? rose->va : rose->vs; 611da177e4SLinus Torvalds end = (rose->va + sysctl_rose_window_size) % ROSE_MODULUS; 621da177e4SLinus Torvalds 631da177e4SLinus Torvalds if (start == end) 641da177e4SLinus Torvalds return; 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds rose->vs = start; 671da177e4SLinus Torvalds 681da177e4SLinus Torvalds /* 691da177e4SLinus Torvalds * Transmit data until either we're out of data to send or 701da177e4SLinus Torvalds * the window is full. 711da177e4SLinus Torvalds */ 721da177e4SLinus Torvalds 731da177e4SLinus Torvalds skb = skb_dequeue(&sk->sk_write_queue); 741da177e4SLinus Torvalds 751da177e4SLinus Torvalds do { 761da177e4SLinus Torvalds if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) { 771da177e4SLinus Torvalds skb_queue_head(&sk->sk_write_queue, skb); 781da177e4SLinus Torvalds break; 791da177e4SLinus Torvalds } 801da177e4SLinus Torvalds 811da177e4SLinus Torvalds skb_set_owner_w(skbn, sk); 821da177e4SLinus Torvalds 831da177e4SLinus Torvalds /* 841da177e4SLinus Torvalds * Transmit the frame copy. 851da177e4SLinus Torvalds */ 861da177e4SLinus Torvalds rose_send_iframe(sk, skbn); 871da177e4SLinus Torvalds 881da177e4SLinus Torvalds rose->vs = (rose->vs + 1) % ROSE_MODULUS; 891da177e4SLinus Torvalds 901da177e4SLinus Torvalds /* 911da177e4SLinus Torvalds * Requeue the original data frame. 921da177e4SLinus Torvalds */ 931da177e4SLinus Torvalds skb_queue_tail(&rose->ack_queue, skb); 941da177e4SLinus Torvalds 951da177e4SLinus Torvalds } while (rose->vs != end && 961da177e4SLinus Torvalds (skb = skb_dequeue(&sk->sk_write_queue)) != NULL); 971da177e4SLinus Torvalds 981da177e4SLinus Torvalds rose->vl = rose->vr; 991da177e4SLinus Torvalds rose->condition &= ~ROSE_COND_ACK_PENDING; 1001da177e4SLinus Torvalds 1011da177e4SLinus Torvalds rose_stop_timer(sk); 1021da177e4SLinus Torvalds } 1031da177e4SLinus Torvalds 1041da177e4SLinus Torvalds /* 1051da177e4SLinus Torvalds * The following routines are taken from page 170 of the 7th ARRL Computer 1061da177e4SLinus Torvalds * Networking Conference paper, as is the whole state machine. 1071da177e4SLinus Torvalds */ 1081da177e4SLinus Torvalds 1091da177e4SLinus Torvalds void rose_enquiry_response(struct sock *sk) 1101da177e4SLinus Torvalds { 1111da177e4SLinus Torvalds struct rose_sock *rose = rose_sk(sk); 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds if (rose->condition & ROSE_COND_OWN_RX_BUSY) 1141da177e4SLinus Torvalds rose_write_internal(sk, ROSE_RNR); 1151da177e4SLinus Torvalds else 1161da177e4SLinus Torvalds rose_write_internal(sk, ROSE_RR); 1171da177e4SLinus Torvalds 1181da177e4SLinus Torvalds rose->vl = rose->vr; 1191da177e4SLinus Torvalds rose->condition &= ~ROSE_COND_ACK_PENDING; 1201da177e4SLinus Torvalds 1211da177e4SLinus Torvalds rose_stop_timer(sk); 1221da177e4SLinus Torvalds } 123