Raspberry pi fan performance

Recently I bought a fan for raspberry pi. The fan is small, and as I could feel the air outtake was not that strong. If I decide to install this fan, I”ll need to drill in the official raspberry pi case. I started to doubt if all the tempering with the official case worth the effort. I decided to perform a test before tempering with the case. I performed three tests with the same command:

sysbench --num-threads=4 --validate=on --test=threads --thread-yields=40000 --thread-locks=6 run

While performing the test I measured the CPU temperature every 5 seconds with the following python code

import datetime
import pause as pause

file="/sys/class/thermal/thermal_zone0/temp"
line=""
output="output.txt"
while (file):
    with open(file,"r") as in_f:
        line=int(in_f.read())
        line=line/1000
    with open(output,"a") as out_f:
        out_f.write("{0},{1}\n".format(datetime.datetime.now().strftime("%H:%M:%S %d/%m/%Y"), line))
    pause.seconds(5)

The first test was with the official raspberry pi case closed, the second test was with the top lid open and the third test was with a lid open and a fan on top of the CPU while I was holding the fan with my hands. Not perfect, but it is what it is.

I arranged the results within a graph with axe Y shows CPU temperature in Celsius, and axe X shows a 5 second tic increments. The results show that with with the lid closed and the lid open the results are fairly close. The difference in graphs (blue and red) exist probably due to a different starting point. The graph shows without any doubt a good boost to temperature handling with a fan (yellow line).

The maximum temperature without a fan in both cases was 81 degrees and with a fan 72 degrees Celsius.

So my conclusion is: if possible, use a fan!

Addition

I tempered with my raspberry pi official case. Added the fan and did a few holes in the case. This is the picture of my crude solution

I added the results with this tempered case to the data from above and the new graph as follows:

Test scenario CPU temperature over time 5 seconds interval

Blue – closed lid
Red – opened lid
Orange – opened lid with fan
Green – lid with installed fan

Temperature goes up to maximum of 71 degrees Celsius with the tempered case

Test scenarioClosed lidOpen lidOpen lid with fanCase with installed fan
Max temperature81817271
Test scenario maximum temperature comparison table

Conclusion stays the same: Use a fan

SSH tunneling

Ssh tunneling allows to route traffic via ssh tunnel. For example, in the following topology I would like to to access 172.217.171.228 on port 80 via 101.1.1.1. But on local port on 192.168.0.10 I would like to go to port 5050.

In that case my command that I”ll issue on 192.168.0.10 will be:

ssh -L 5050:172.217.171.228:80 username@101.1.1.1

This command will open ssh to 101.1.1.1 from 192.168.0.10, and will hold local port 5050 on the Client open. Every connection that is made to localhost:5050 on the Client will be forwarded to the SSH session and from the “SSH tunnel intermediate” will open session to 172.217.171.228:80

There also another option for ssh tunnel, where the Server connects to client, and then on the client machine user can open connection to some local port and the session ends up in the server.

The following command will make this happen:

ssh -R 5050:localhost:80 username@192.168.0.10

In that case the Server will open ssh session to the Client. Every connection made on the client to port localhost:5050 will be forwarded to 172.217.171.228

With the same topology described above, I want to access any server from any port. In that case, the command will be used:

ssh -D 5050 username@101.1.1.1

This will act as a SOCKS server. Meaning, after ssh established to 101.1.1.1 from 192.168.0.10, every connection that is made to localhost:5050 will be forwarded to outside world with random port from 101.1.1.1. This is useful if some proxy is used to firewall your connections to the internet. The initiator of the connection needs to work with SOCKS4 or SOCKS5 protocol. Firefox can be this initiator.

To configure SOCKS in firefox, in address on top write and go to about:preferences. Search for proxy in search field. Click on settings and write localhost in address and port number 5050 under “SOCKs host”

Obviously the ssh server needs to support ssh tunneling. My ubuntu did not support this by default. To enable this in the file /etc/ssh/sshd_config this configuration should be applyed:

AllowTcpForwarding yes
GatewayPorts yes

After this configuration changed, ssh service should be restarted

service ssh restart

TMUX cheat sheet

Tmux is a terminal that I often use. Great benefits are if ssh disconnects the terminal remains and if I run some command, it continues to run. Other benefit is same screen for two or more ssh connections.

These are more common basic command to use in tmux

Start a new session with a specific name

tmux new -s session-5

By default , after entering the command “tmux”, sessions are named with a number

List sessions tmux ls

tim@tim-linux:~$ tmux ls
0: 2 windows (created Sun Oct 11 13:10:12 2020) (attached)
session-5: 1 windows (created Tue Oct 13 11:26:48 2020)
tim@tim-linux:~$

There are two sessions in this computer, named 0 and session-5.

Connect to specific session

tmux attach -t session-5

I”ll use C^ to specify CONTROL and M^ to specify ALT button. The control character for tmux is C^b. After this combination is pressed user enters control mode and perform actions like copy and paste, split windows etc.

Split session vertically

C^b %

Split session horizontally

C^b "

The result of splitting first vertically then horizontally looks like the following:

Navigate between open windows

C^b arrows

Open new window

C^b c

Detach – exit from tmux, but leave the session running

C^b d

To copy in tmux, first click C^b [. With arrows go to desired text click C^SPACE. Select desired text with arrows. Click M^w. Text copied.

To paste go to desired location to paste , click C^b ]

Tar cheat sheet

I don’t use tar very often. However every time I do, I don’t remember the switches and options. So I am making this post in order to remember the basics of the tar command.

Store files in a new archive (option -c), in file name arch.tar (option -f indicates file name), while show all output (-v).

tar -c -v -f arch.tar .

This will be the same as :

tar -cvf arch.tar .

From now on will use a short way of giving commands to the tar.

To archive files with compression add switch for compression. For gzip add -z:

tar -cvzf arch.tar .

List files (-t) within the archive (-f) arch.tar, while showing verbose output (-v) :

tar -tvf arch.tar

Extract files (-x) from archive (-f) arch.tar, while showing verbose output (-v):

tar -xvf arch.tar

Extract to specific directory use -C switch.

tar -xvf arch.tar -C arch

Python libraries for networking

Someone told me about these python libraries for python for networking. I am sure that I will not remember them by heart, so I will write these libraries here, in order to remember

  • Asyncio – Python standard library. Asynchronous I/0, event loops, coroutines and tasks
  • Diesel – coroutine-based networking library for python
  • Pulsar – Event driven concurrent framework for Python
  • NAPALM (Network Automation and Programmability Abstraction Layer with Multivendor support) is a Python library that implements a set of functions to interact with different network device Operating Systems using a unified API.
  • Twisted – an event-driven networking engine written in Python 

Capturing traffic on an interface and reviewing later in wireshark on Cisco CSR 1000v

TL;DR: On CISCO router, capture traffic locally to a pcap file and send it later to your computer.

I don’t know how did I missed that! I needed to capture a traffic on an interface, however for some reason, i couldn’t use live capture. So I was trying to find a way to capture, using the “?” a lot in CISCO terminal. Accidentally, I found a way to store a capture locally. I pretty sure everyone knows about this but me, but I”ll write this anyway.

After the capture is complete it needed to be sent somewhere. In my case I will send it to tftp server. So make sure you have tftp server running somewhere.

Performing the capture

Configure capture to match some traffic. In my case I want to capture any IPv6 traffic. For me the command would be :

Router# monitor capture cap_name match ipv6 any any interface gigabitEthernet 2 both

The command breakdown with some of the fields explained:

Router#monitor capture cap_name match ipv6 any any interface gigabitEthernet 2 both
                        ^              ^    ^   ^
                        |              |    |   +----------------+
              +---------+  +-----------+    +-------------+      |
              |            |                              |  Destination selection
              +            +                              |
   Capture name    Match traffic type                Source selection
                     any   all packets                 A.B.C.D/nn  IPv4 source Prefix ...
                     ip^4  IP^4 packets only              or
                     ipv6  IPv6 packets only           X:X:X:X::X/<0-128>  IPv6 source...
                     mac   MAC filter configuration    any         Any source prefix
                                                       host        A single source host
                                                       protocol    Protocols

Now I can start the capture:

Router# monitor capture cap_name start

Now the capture runs. It is probably a good idea to have some good match for a specific traffic to make sure to keep the capture file small and memory of the CISCO free.

While the capture runs, I can check it status:

Router#show monitor capture cap_name

Status Information for Capture cap_name
  Target Type:
   Interface: GigabitEthernet2, Direction: both
   Status : Active
  Filter Details:
   IPv6
    Source IP:  any
    Destination IP:  any
   Protocol: any
  Buffer Details:
   Buffer Type: LINEAR (default)
   Buffer Size (in MB): 10
  Limit Details:
   Number of Packets to capture: 0 (no limit)
   Packet Capture duration: 0 (no limit)
   Packet Size to capture: 0 (no limit)
   Maximum number of packets to capture per second: 1000
   Packet sampling rate: 0 (no sampling)

When the capture is done, I can stop it:

Router#monitor capture cap_name stop

And now I need to send the capture to my tftp server:

Router#monitor capture cap_name export tftp://10.0.0.44/my_capture.pcap
!
Exported Successfully

Other destinations where a traffic can be exported to:

Router#monitor capture cap_name export ?
  bootflash:  Location of the file
  flash:      Location of the file
  ftp:        Location of the file
  http:       Location of the file
  https:      Location of the file
  pram:       Location of the file
  rcp:        Location of the file
  scp:        Location of the file
  tftp:       Location of the file

This is it! Just open the file you’ve received in wireshark.

Kernel programming seminar.

I have a kernel programming seminar at my job. The idea is to enrich knowledge and to ‘fortify’ what I already know.

In my experience, in order to truly learn and remember what I learned is to write it down. I will write my notes here in a hope that I don’t forget what I’ve learned. In case I do forget, I always can come here, and remind myself what I’ve learned.

So the next few posts will be my personal notepad available for everyone.

Part 1 – Introduction

One of the method to program in kernel is to use modules. In most cases these are drivers.

To compile a module, it is required to compile the module with the source code of the kernel – so called headers.

When compiling a module, use Makefile:

obj-m += acme.o
KDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

EXTRA_CFLAGS = -g

default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

The compilation result file ends with .ko. This file needs to be part of kernel. To insert or remove this file from the kernel the following commands can be used:

insmod <file name> – insert module file into the kernel
rmmod <module name> – remove module from kernel
lsmod – list modules loaded into kernel

Module has to have two functions: one activates when loading file to kernel, the other activate when removing module from kernel:
module_init(acme_init);
module_exit(acme_exit);


The function init will be called with the __init preamble :
static int __init acme_init(void)
{
}


The function exit will be called with the exit __preamble:
static void __exit acme_exit(void)
{
}

The module should have these definitions:
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Example character driver");
MODULE_AUTHOR("Free Electrons");


If license differ then GPL, dmesg log will show that the kernel is tainted:
module license 'Proprietary' taints kernel.

kernel module hello world program:

#include <linux/init.h>
#include <linux/module.h>

MODULE_LICENSE("Proprietary");

static int __init hello_init(void)
{
printk(KERN_ALERT "Hello, world\n");
return 0;
}

static void __exit hello_exit(void)
{
printk(KERN_ALERT "Goodbye, cruel world\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_AUTHOR("Tim Goldshmit");
MODULE_DESCRIPTION("Tim's HELLO module");
MODULE_LICENSE("GPL");

VM inside a VM inside another VM

TL;DR: How do you call a tolopogy where you have virtual machine inside virtual machine inside another virtual machine? Virtual machine inception.

I need to help to setup facilities for a kernel seminar. Each participant must have a virtual machine. This VM provided by the company that organizes the seminar.

The company sent me this VM. It was made in newest VMware player. For some reason, after googling a lot, and following few guides, I couldn’t add it to my old ESXi server. I guess VMware didn’t make this software back compatible.

So instead, i took an easy way out. I created a VM, and installed several VMs inside the 1st VM. I am limited to 8 cores for the 1st VM. So I cloned this one also.

I decided to call this setup “virtual machine inception”. As this reminded me of the movie “inception”, where the protagonist goes into a dream, and within the dream goes into another dream.

C vs Python

I saw this picture on Instagram on page of some guy that teaches python

I assume that what this guy meant is that python fits best for some kind of applications than c, and for some kind of applications c fits better than python, and not that c generally sucks compared to python.

Linked List

Linked list, is a dynamic data structure in c to store data. This post is cheat sheet to myself, for every time I need to build a linked list. This is not necessary the correct way of creating the linked list, but this is my way.

Main file.

/*
 ============================================================================
 Name        : LinkedList.c
 Author      : Tim Goldshmit
 Version     :
 Copyright   : Your copyright notice
 Description : Hello World in C, Ansi-style
 ============================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include "mylinkedlist.h"

int main(void)
{
	puts("!!!Kick this into gear!!!");
	struct my_list temp;
	memcpy(temp.mydata.full_name,"tim g",sizeof(temp.mydata.full_name));
	temp.mydata.id=1000;

	// create the root or the first node
	struct my_list root;
	memset (&root,0,sizeof(struct my_list));

	int i;
	for (i=1;i<10;i++)
	{
		temp.mydata.id=i;
		add_to_list(&root,&temp);
	}

	struct my_list *p;
	p=&root;

	remove_n_from_list(p,5);

	free_all(&root);

	return EXIT_SUCCESS;
}

the .h file

/*
 * mylinkedlist.h
 *
 *  Created on: Oct 6, 2019
 *      Author: timg
 */

#ifndef MYLINKEDLIST_H_
#define MYLINKEDLIST_H_

struct my_data
{
	char full_name[50];
	int id;
};

struct my_list
{
//	struct my_list *head;
	struct my_list *prev_node;
	struct my_list *next_node;
	struct my_data mydata;
};

int add_to_list(struct my_list *current_list,struct my_list *new_entry);
int free_all(struct my_list *any_entry);
int remove_n_from_list(struct my_list *entry_to_remove,int n);
#endif /* MYLINKEDLIST_H_ */

The .c file

/*
 * mylinkedlist.c
 *
 *  Created on: Oct 6, 2019
 *      Author: timg
 */

#include <stdio.h>
#include "mylinkedlist.h"
#include <stdlib.h>
#include <string.h>

/**
 * Add to the end if the list
 * current_list - any member of the list
 * new_entry - data to enter. the pointers do not matter, it only copies the data
 */
int add_to_list(struct my_list *current_list,struct my_list *new_entry)
{
	//In case not at the end of the node. Move to the last node
	while (!current_list->next_node==NULL)
	{
		current_list=current_list->next_node;
	}

	struct my_list *new_node=(struct my_list*)malloc(sizeof(struct my_list));
	memset (new_node,0,sizeof(struct my_list));
	current_list->next_node=new_node;
	new_node->prev_node=current_list;
	memcpy(&new_node->mydata,&new_entry->mydata,sizeof(struct my_data));
	return 0;
}

/**
 *  Remove node number n from the list.
 *  To remove current node, in the list send address of the
 * node to the function with n=0
 */
int remove_n_from_list(struct my_list *entry_to_remove,int n)
{
	int i;
	for (i=0;i<n;i++)
	{
		if (entry_to_remove==NULL)
			return -1;
		entry_to_remove=entry_to_remove->next_node;
	}

	if (entry_to_remove->prev_node==NULL && entry_to_remove->next_node!=NULL)
		entry_to_remove->next_node->prev_node=NULL;
	else if (entry_to_remove->next_node==NULL && entry_to_remove->prev_node!=NULL)
		entry_to_remove->prev_node->next_node=NULL;
	else if (entry_to_remove->next_node!=NULL && entry_to_remove->prev_node!=NULL)
	{
		entry_to_remove->prev_node->next_node=entry_to_remove->next_node;
		entry_to_remove->next_node->prev_node=entry_to_remove->prev_node;
	}

	free (entry_to_remove);
	return 0;
}

/**
 * Frees all of the memory of the linked list
 */
int free_all(struct my_list *any_entry)
{
	// get to the first node
	while (!any_entry->prev_node==NULL)
		any_entry=any_entry->prev_node;

	// free nodes one by one
	struct my_list *temp;
	while (!any_entry==NULL)
	{
		temp=any_entry->next_node;
		free(any_entry);
		any_entry=temp;
	}


	return 0;
}

This also stored in github.

https://github.com/timgold81/LinkedList