Friday, April 14, 2017

Caja: Check MD5sum in a Context Menu

This post applies only to the Caja file manager. It's used in Linux Mint, and likely other distributions.

Why Calculate an MD5 Checksum?

Free software is available all over the Internet. An unfortunate side effect, however is that you download something that has been surreptitiously replaced with malware, or other such malfeasance. Also, minor disruptions in data transfers have the ability, rare as it is, to cause a deformed packet, which still makes it past basic error checking mechanisms. So we want to validate files that we download to ensure they are reputable, and unchanged from the originals. Reputable websites that offer downloads will often display an MD5 checksum value (a string of characters and digits), typically placed near the download link. You will usually see the code preceded with "MD5: ", "md5sum: ", or similar. This code is calculated based upon the contents of the file that it represents, and if you perform an MD5 checksum of the file on your computer, it should match what is displayed on the website.

Why Wouldn't You Calculate an MD5 Checksum?

There are a few reasons we don't do this. First, many sites don't provide an MD5 checksum value. There's not much we can do about that, other can contact the website owner and request one. Even when there is a checksum value displayed, it's cumbersome, and it takes time for larger files. You have to open a terminal shell locate the file, run the md5sum command... In a word, it's inconvenient. This is where cajamd5 comes in. This is a small shell script that you can add to the Caja file manager to make checking an MD5 quick and easy.

Creating the Script

First, we need to write our script. Open your favorite text editor, and type in the following:

#!/bin/bash

for file in $CAJA_SCRIPT_SELECTED_FILE_PATHS
do
  # Begin calculating the md5 sum of a file.
  md5sum "$file" | tee >(cut -d ' ' -f1 > /tmp/sum) |zenity \
         --progress --title="MD5sum" --text="Calculating MD5 \
         for:\n${file##*/}" --pulsate --auto-close

  # This block exits the operation if the user clicks Cancel.
  if [ "${PIPESTATUS[2]}" -ne "0" ]; then
    rm /tmp/sum
    exit 0
  fi

  # Calculation is finished, so display the result.
  sum=$(cat /tmp/sum)
  zenity --info --title="MD5sum" --text="MD5sum : $sum\nFile : \
        ${file##*/}"
  rm /tmp/sum
done

exit 0

Save the file in your home directory as with the name cajamd5.

Preparing the Script for the Menu

This is pretty simple, actually. All we need to do is make the script executable, then copy it into a directory Caja uses for scripts. To do this, Click the Menu, then Terminal.
In the terminal, type in the following (just what's in bold):

you@computer ~ $ chmod +x cajamd5
you@computer ~ $ mv cajamd5 ~/.config/caja/scripts
you@computer ~ $ exit

That's it. You can now calculate an MD5 checksum on any file from within the graphical Caja file manager.

Below is a quick step-by-step of checking an MD5 sum. You'll want to click each image to get a better view.

When you right-click on the file, the context menu appears, and you now have a Scripts option at the top, with our new script in it. Just left-click the cajamd5 item.





This automatically starts the md5 sum calculation against the file you selected.




After a short period of time, a new window is opened displaying the MD5 sum for the file, and the file name. If you compare the value in the cajamd5 box with the MD5 sum under the second item in the list, you'll see they are the same.



All done. We can now ensure the files we download are what the publisher intended, quickly and easily.

One small note: Caja will allow you to select multiple files, and calculate MD5 sums on all of them with one click of the cajamd5 script. This is done one file at a time. Normally it's not a big deal, but if the files are large (such as multiple .ISO images), this can take a while.

Credits:
  • Ethan J. Eldridge provides a basic script on his blog to execute an action in Caja.
  • Belham2 posted the code for calculating the MD5 sum, and displaying in a window on the Solus Project forums.

Thursday, March 2, 2017

Secure Tomcat Servlets Behind Apache httpd

OVERVIEW


We take the tomcat/httpd configuration we created in THIS POST, and we secure those applications using HTTPS. We will be using a self-signed certificate in this example, but the process is essentially the same for trusted certs, providing they come as .key, and .cert files. Again, I assume you are familiar with the command line in Linux, and all work will be performed as root.

Below is a simple diagram that illustrates our application architecture.

A secured application
We'll be working strictly between the two blocks on the far right of the diagram. We will secure the connection between the client browser and the Apache httpd server. Virtually everything I've read to this point indicates that the connection from the httpd server on to the actual applications do not require the same level of security. Consider that Tomcat may reside on the same physical host as the httpd server, or that the httpd server is a perimeter device, thus connections behind it are internal, and thus considered secure (at least, reasonably).

SECURE THE HTTPD TRAFFIC


This is a short, 5-step process. We will be securing traffic using openssl/mod_ssl.

Install mod_ssl


If you followed the process of placing tomcat behind httpd in my previous post, you know that we're using CentOS 6, and we installed the version of httpd server compiled for RHEL/CentOS that is available via the default yum repository. We'll be using the same for mod_ssl, which makes installation as easy as:

# yum install mod_ssl

Create a Directory to House the Certificate and Key Files


# mkdir /etc/httpd/ssl

Create the Self-Signed Certificate


# openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/httpd/ssl/apache.key -out /etc/httpd/ssl/apache.crt

You will be prompted for a number of pieces of information. Provide answers to each, paying close attention to the Common Name field. This will be the DNS name or IP address of your httpd server. Once created, the certificate and key files are valid for one year, and will be dropped into our custom directory created above.

Configure the httpd Server to Use the Certificate


Edit the /etc/httpd/conf/ssl.conf file:

# vim /etc/httpd/conf/ssl.conf

Locate the <VirtualHost _default_:443> section. We will be working inside that block. Uncomment the DocumentRoot and ServerName lines, and replace the example.com with your server name.
Next, locate the following three keys, and set to the values indicated below:

SSLEngine on
SSLCertificateFile /etc/httpd/ssl/apache.crt
SSLCertificateKeyFile /etc/httpd/ssl/apache.key


Save the file, and exit back to the command prompt.
Test the Apache httpd config, and Restart httpd:

# apachectl -t (should come back with "Syntax OK")
# service restart httpd


Now, if you browse to the document root of the server, you should see the Apache httpd test page that comes with CentOS, and you should see in the address bar that you are using HTTPS (though there will likely be a warning symbol of some sort, as the certificate is self-signed).

Enable Secure Access to Tomcat Servlets


Try to browse to the tomcat examples directory, and you will notice a "Not Found" error. This is because while we configured httpd for HTTPS, we're not passing that back to tomcat yet. As it turns out, this is very simple. Edit the ssl.conf file, and go back into the <VirtualHost _default_:443> section.

# vim /etc/httpd/conf/ssl.conf

Add the following two lines:

JkMountCopy On
JkMount /* ajp13


Save and close the file.

Now when you browse to the examples directory using https (https://<server-name-or-ip>/examples/) you should see the examples directory. Clicking on the Servlet examples link will show the page of example servlets provided by tomcat.
Accessing Tomcat servlets over https

Run Tomcat Behind Apache httpd

OVERVIEW


I ran into an issue recently where I needed to set up Apache Tomcat behind the Apache httpd web server. The book I was referencing was a bit dated, and sources on the web always seemed to leave out a critical piece of information. I'm documenting here, in the event someone might find it useful. Note that this procedure is less about installation (though I touch on it briefly) and more about the actual connection process between the two components.

I assume you are familiar with working around the command line in Linux. All commands here are also performed as root.

Why use Apache httpd as a front-end to Tomcat?



  • Clustering/Load Balancing: mod_jk (the module we will use) provides a nice load-balancing feature set allowing you to set up multiple tomcat servers behind the httpd server.
  • Security: You can implement security through httpd, which has a more mature feature set, and is well understood by the community. In addition, you have the flexibility to move security settings between tomcat and httpd (where such settings overlap).
  • Flexibility: We can leverage the many add-on modules and extensions of httpd.
  • Socket Error Handling: Since httpd runs natively on Linux, it has the ability to interact directly with socket errors.

What is the environment we're working in?


We'll be configuring the following:
  • Architecture: x86_64
  • OS: CentOS Linux 6.8 (This will work equally well on Red Hat Enterprise Linux 6)
  • Web Server: Apache httpd 2.2 (using the server built for CentOS 6 from the default yum repo)
  • Tomcat: Apache Tomcat 8.5.11, pulled from the Apache website (apache-tomcat-8.5.11.tar.gz)
  • Java: Oracle Java 8 (1.8.0_121) downloaded from Oracle.com (jdk-8u121-linux-x64.tar.gz)

INSTALLATION

Java


Install Java, and set the JAVA_HOME environment variable in root's .bash_profile:

JAVA_HOME=/usr/java/jdk1.8.0_121
PATH=$PATH:$JAVA_HOME:$HOME/bin
export PATH

As you can see, I simply uncompressed the tarball into /usr/java (thus bypassing fully the 'alternatives' functionality. If you are not aware of alternatives in RHEL/CentOS - read up on it; it's pretty interesting from a flexibility perspective). There are plenty of tutorials on the web for Java - seek one out if you have issues.

Apache httpd


We're using the stock httpd that comes with RHEL/CentOS, so it's really as simple as:

# yum install httpd

Tomcat


Drop the Tomcat tarball into /usr/share, then extract it (from within the same directory):

# tar -zxvf apache-tomcat-8.5.11.tar.gz
# rm apache-tomcat-8.5.11.tar.gz

This will create a directory /usr/hare/apache-tomcat-8.5.11 containing all of the files required for tomcat. Once done, we remove the tarball. It is no longer needed.

We also need a start/stop script for tomcat. Every good service should have a start/stop script for management. 

# cd /etc/init.d/
# vim tomcat

Paste in the following:

#!/bin/bash
# description: Tomcat Start Stop Restart
# processname: tomcat
# chkconfig: 234 20 80

if [ "$JAVA_HOME" == "" ]; then
    JAVA_HOME=/usr/java/jdk1.8.0_121
    export JAVA_HOME
    PATH=$JAVA_HOME/bin:$PATH
    export PATH
fi

CATALINA_HOME=/usr/share/apache-tomcat-8.5.11

case $1 in
    start)
      sh $CATALINA_HOME/bin/startup.sh
      ;;
    stop)
      sh $CATALINA_HOME/bin/shutdown.sh
      ;;
    restart)
      sh $CATALINA_HOME/bin/shutdown.sh
      sleep 1
      sh $CATALINA_HOME/bin/startup.sh
      ;;
esac

exit 0

and save the file. Next we make the file executable, add it to chkconfig and test.

# chmod +x tomcat 
# chkconfig tomcat on
# chkconfig --add tomcat
# chkconfig --level 234 tomcat on
# chkconfig --list tomcat
# service tomcat start

At this point you should be able to browse to the host on port 8080, and see the tomcat page:

We have validated that Tomcat is up and running.


If there are any issues, search for "Exception" in /usr/share/apache-tomcat-8.5.11/logs/catalina.out.

CONNECTING HTTPD AND TOMCAT


First, we need to find the mod_jk.so module. For the newcomer, this can be a little challenging, since many of the links to the binaries provided on the tomcat site link only to Windows versions, and the name of the binary listed is not mod_jk.so (as one might expect). I'm using the binary version, and pulled my version from HERE. Given the versions of middleware components specified above, you'll want mod_jk-1.2.31-httpd-2.2.x.so.

The following will download the file, name it appropriately, and drop it in the correction location:

# wget https://archive.apache.org/dist/tomcat/tomcat-connectors/jk/binaries/linux/jk-1.2.31/x86_64/mod_jk-1.2.31-httpd-2.2.x.so
# mv mod_jk-1.2.31-httpd-2.2.x.so mod_jk.so
# cp mod_jk.so /usr/lib64/httpd/modules/
# chmod 755 /usr/lib64/httpd/modules/mod_jk.so

Next, we need a configuration file for httpd to tell it about the module, and it's settings. Note that this file should go into the conf.d directory for all httpd add-on configuration files (default: /etc/httpd/conf.d/)

vim /etc/httpd/conf.d/tomcat.conf

Paste in the following:

# Load the module
LoadModule jk_module modules/mod_jk.so

# Where to find workers.properties
# Update this path to match your conf directory location (put workers.properties next to httpd.conf)
JkWorkersFile /etc/httpd/conf/workers.properties

# Where to put jk shared memory
# Update this path to match your local state directory or logs directory
JkShmFile     /var/log/httpd/mod_jk.shm

# Where to put jk logs
# Update this path to match your logs directory location (put mod_jk.log next to access_log)
JkLogFile     /var/log/httpd/mod_jk.log

# Set the jk log level [debug/error/info]
JkLogLevel    info

# Select the timestamp log format
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "

# Send everything for context /examples to worker named worker1 (ajp13)
JkMount  /examples/* worker1

Save the file and exit vim.

Finally, we need to configure Tomcat with the settings for the worker that we referenced in the tomcat.conf file. This file should be located in the same directory as the main httpd server configuration file, httpd.conf.

vim /etc/httpd/conf/workers.properties

Paste in the following:

# Define 1 real worker using ajp13
worker.list=worker1

# Set properties for worker1 (ajp13)
worker.worker1.type=ajp13
worker.worker1.host=localhost
worker.worker1.port=8009

Save the file, and exit vim.

We'll do a quick config test, then restart both services to pick up the changes, and perform a full test:

# apachectl -t
# service httpd restart
# service tomcat restart

Browse to http://<server-name-or-ip>/examples/

You should see the following:

The main Tomcat examples page, brought to you by Tomcat


So how do we know the examples page is being handled through Apache httpd? Note in the URL, the lack of a port # (8080 was the port we configured tomcat to run on earlier, and was required). When we specified "examples/" as our desired URL, and left off the port 8080, the request went to httpd on port 80, httpd used mod_jk and it's associated configuration files to discover that tomcat is serving up "examples", and then forwarded the request along. Tomcat responded with the page, which was then returned to the browser by httpd.

---
In the NEXT POST, we will secure access to the Tomcat servlets using HTTPS.

REFERENCES


Sunday, January 8, 2017

Analyzing UDP Performance

I came upon an issue where there was concern about external factors that might impact receipt and processing of UDP packets. Specifically, the question was why am I dropping UDP packets? There are a multitude of explanations, but since the answer isn't nearly as much fun as the search, here's how I started to investigate the problem. This post is focused strictly upon the process, not the answer.

Based upon the query, I knew walking into this the following:
  • irqbalance was in play, so the potential existed for a process to move around.
  • Other processes ran on the host (no big surprise), but admin processes should have all been pinned to CPU0.
  • The process in question (that consumed the UDP traffic) was being pinned to another CPU (not CPU0).
  • The fluctuation in the UDP receive queue implied that something was taking place on the same CPU, temporarily halting the movement of data from the buffer to the application.

The Lab


The target host is a 4-core Intel Xeon (2 sockets x 2 cores each) host with a 1Gbit Full duplex NIC. It's running CentOS 7.2 (build 1511). The application written for testing is written for (and run in) Python 2.7. The client is a Linux Mint desktop, also with a 1 Gbit NIC, full duplex.

Generating Traffic


To begin with, we need a way to induce UDP traffic at a pretty high rate (we want to induce load). I came across a wiki page at python.org that explained how to pass a message via UDP using a client/server application. I extended it into something that would do the same at a very high rate. Here's the code:

Server Side Application


#!/usr/bin/python

# udpconsumer.py: Open a port to read inbound UDP packet data

import socket

# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# Bind the socket to the port.
server_address = ('0.0.0.0', 10000)
print 'starting up on %s port %s' % server_address
sock.bind(server_address)

while True:
    data, address = sock.recvfrom(4096)
    print data



We begin by including the necessary modules, and creating the socket. Next we bind the socket to all interfaces (essentially, unlocking the door to allow traffic in). After a short message to the user, we enter an infinite loop that does nothing more than read the data being sent by the client application below, and printing it to the console (nice to know the app is working, but if you want even higher frequency, eliminate the print statement; then your server can process traffic at a higher rate.

Client Side Application


#!/usr/bin/python

#udptg.py: UDP traffic generator

import socket
import sys

#Create a UDP socket
try:
    sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
except socket.error, msg:
    print 'Failed to open socket. Error code: ' + str(msg[0]) + ': ' + msg
    sys.exit()

server_address = ('172.16.1.195', 10000)
pktcounter = 0

while True:
    pktcounter += 1
    # send data
    pkt_msg = str(pktcounter)
    sent = sock.sendto(pkt_msg, server_address)



In this app, we include our modules and open the socket. Next we specify where we are sending traffic (IP and port). We set a counter - this will end up being both the payload data, and the count of UDP packets sent. We create another infinite while loop to send data (the incrementing counter value).

Running the Applications


On the server, we start the server with:

    # ./udpconsumer.py

It will display a message, then just sit and wait for data.


On the client, when it comes time to send data, we initiate the script with:

    # ./udptg.py

When this is done, you can watch the terminal where the server started, and you should see numbers being output that increment by 1 on each line.

Measurement


OK, so with that, now we need some tools to measure what's going on. There are a few things I want to look at to start with. These include:

Size of the UDP buffer (how much stuff is waiting for the application)

Impact to CPUs (Utililzation)


Context switches (how often our ability to process inbound data is being interrupted)

Fortunately, these are not difficult to measure. To capture the buffer size, we can issue the following command:

    # while [ 1 ]; do netstat -lun | grep 10000 | awk \
      '{print $2}';sleep .1;done > file.dat

This polls the netstat command for UDP sockets, and filters out everything except the receive queue size, which is measured in bytes. It will produce a file with numbers on each line. Drop that into a spreadsheet to graph, grab average and standard deviation stats, and you have a good picture of what's happening in the UDP receive buffer.

Obtaining CPU utilization and context switches is just as easy. Each of the following will get that for you:

    # sar -P ALL   #displays CPU utilization on each CPU, and for
                   #all of them collectively.

    # sar -w       # shows context switches per second.


One important note for the sar data: you might consider increasing the interval from the default 10 minutes to 1 minute. The values sar displays are not point-in-time, but rather an average across the interval. By shortening the interval, your test runs don't need to be as long to get valid data. I set to 1-minute intervals, and ran the test for just over 7 minutes, throwing out the first and last minutes.

Poking the Bear to See What Happens


Now that we can watch what's happening, we want to play with some tunables to see what impact they have on overall performance. There are two things I've looked at: CPU pinning, and scheduling. By default, processes can run on any CPU, and can be switched around as the OS feels is necessary. In addition, the default CPU scheduler is SCHED_OTHER, and the default priority is 0 (basically, every process gets equal treatment. In our test, we want to see what happens if we force the kernel to only allow the application on a single CPU, and if we give that process more CPU time through the scheduler. The commands that allow this are taskset and chrt. We need to be able to do two things for each: set the values, and get (display) the values.

Getting taskset and chrt Values


First, obtain the pid of the process. Since the server-side application just sits and waits for traffic, we can start it up, and get its pid from the process table. As long as we don't kill the server application, we can reuse the same pid throughout the exercise.

    # ps ax | grep [u]dpconsumer

The first value on the line will be the pid (which in this case, is 17648).

The following illustrates checking the current scheduler configuration:

    [root@nebula sysadmin]# chrt -p 17648
    pid 17648's current scheduling policy: SCHED_OTHER
    pid 17648's current scheduling priority: 0


Here, we check the CPU affinity:

    [root@nebula sysadmin]# taskset -pc 17648
    pid 17648's current affinity list: 0-3
    [root@nebula sysadmin]#


Now that we know how to inspect the settings, we need to be able to modify them.

Let's change the scheduler to giver our application something more of real-time priority, and verify the change:

    [root@nebula sysadmin]# chrt -f -p 99 17648
    [root@nebula sysadmin]# chrt -p 17648
    pid 17648's current scheduling policy: SCHED_FIFO
    pid 17648's current scheduling priority: 99


Our process now takes advantage of a first-in-first-out scheduler, with a priority of 99 (nearly pushing other processes out of the nest). Note that once you do this, everything else slows down, including ssh sessions into the host.

Next, we're going to pin the process to run only on CPU3.

    [root@nebula sysadmin]# taskset -p 08 17648
    pid 17648's current affinity mask: f
    pid 17648's new affinity mask: 8
    [root@nebula sysadmin]# taskset -pc 17648
    pid 17648's current affinity list: 3


There is a little black magic, here. The command uses a mask as the -p parameter, which allows you to set the affinity to not only a single CPU, but any combination of all of the CPUs. This is handy, but requires that you understand how to translate the mask value (f) to one or more CPUs, and vice versa. This is pretty well documented in the taskset documentation.

Test Design


OK, so we can see how to inspect the queue, CPU utilization, and context switching, and we know how to change a few tunables that might impact those values. Let's put them all together.

I set up a test that consisted of 4 runs (tying the scheduler/priority to a single variable; you can split them out, but that then would reqiure 8 runs). For each run, I started by invoking the udptg.py application on the client (we executed udpconsumer.py earlier to get the pid, and it's still running on the server). After waiting a few seconds, I then kicked off the netstat command in the while loop on the server. Let that run for 7 minutes, then kill the while/netstat command, followed by killing the udptg.py command. After a minute or two of rest, I issue the sar commands, and capture the output. The reason we wait a few minutes is to allow periods of low activity to sit in between the test runs. This makes it easier to differentiate the periods of testing from each other.

Next we issue a taskset or chtr command (but only one at a time; if you found this page, you already understand the perils of measuring the impact of changing two variables at the same time).

Start the next test the same as the first, rinse and repeat through all four combinations.

Here's the result from testing in my lab:

AFFINITY       ALL        CPU 3      CPU 3      ALL
PRIO/SCHED     0/OTHER    0/OTHER    99/FIFO    99/FIFO

-------------------------------------------------------
AVG Q SZ        204448     207177      55571      51660
STD_DEV          24866      17924      90645      88253
CPU Util% Avg     42.0       96.2       49.3       14.7
CSWITCH/s     234035.3   242664.8    16752.4    17020.4






This shows the impact of CPU utilization across all CPUs during each of the 4 tests.

Here we see the impact of CPU utilization of CPU 3. We've removed much of the impact on CPU 0, at the expense of CPU 3.

In our context switches, we see that the impact of increasing the priority for our application really stopped much of the swapping of processes in and out of the CPUs. This may be bad for our server, but is good for the application.

TODO


There are certainly other variables you can change. If you're dropping packets, you can increase the buffer size, but all this really does is prolong the inevitable. There are other things to test as well, but this is really just a first pass. You might also consider pinning all administrative OS activity to a single CPU. This will get it off the pinned CPU (you didn't pin your application to CPU 0, did you?) In addition, if you're running other production applications, you might consider pinning them to CPUs other than where you're running your test in a second round, and observing the receive queue statistics.

I have intentionally avoided providing a conclusion. There are still some outstanding items (in addition to those above) that are not fully understood, and as such, it's difficult to infer a course of action. Most notably, there are a number of rows in the output of the netstat command with the value '213312' (many more than one would expect to occur organically). My initial hypothesis is that this is the maximum size of the buffer. I still need to understand why this value appears so frequently. In addition, there are roughly 44M UDP packet receive errors as reported in 'netstat -s', but no drops reported in the output of ifconfig. Finally, I am not comfortable with the excessive standard deviation listed for the last two columns. It's surely related to the appearance of '213312' in the data, but needs to be confirmed. All that said, We've at least made a start in understanding how to reduce the buildup of data in the UDP buffer.

UPDATE 1


I ran the third configuration (pin the application to CPU3, PRIO=99, scheduler=FIFO) again, but this time, islolated CPUs 2 and 3 from all other processes. This was accomplished by adding

     isolcpus=2,3
 
to the end of the GRUB_CMDLINE_LINUX line in /etc/default/grub, reinstalling grub (grub2, actually) with:

     # grub2-mkconfig -o /boot/grub2/grub.cfg

and finally, rebooting. A Quick look at the output of 'sar -P ALL' confirmed that there was no activity on CPUs 2 and 3. Here is the comparison of the two sets, changing only the CPU isolation:

ISOLCPUS       N/A        2,3
AFFINITY       CPU 3      CPU 3
PRIO/SCHED     99/FIFO    99/FIFO

---------------------------------
AVG Q SZ         55571       6754
STD_DEV          90645       8761
CPU Util% Avg     49.3       44.0
CSWITCH/s      16752.4    15507.6


The receive Q size is just over 10% of the previous value, the standard deviation is less than 10% what it was, and we trimmed another ~5% off CPU utilization for the core. This is a huge improvement, but by no means, deterministic, yet. In addition, the '213312' value is still showing up in the output of the netstat command, and our context switches show only minimal improvement.

I next tried to test the hypothesis that  213312 is the UDP receive buffer size. By adding the two following statements before the while loop, we can get and print the buffer size:

udprcvbufsz = sock.getsockopt(socket.SOL_SOCKET,socket.SO_RCVBUF)
print 'UDP Recv Buffer Size: ' + str(
udprcvbufsz) + ' bytes'

This returns the value 212992, which is exactly 320 bytes smaller than our mystery value. I read that TCP reserves some of the TCP buffer space for admin purposes, and I think this may be the case (but still need to research this).

I also captured the pre- and post-netstat statistics (netstat -s), and found the following:

Metric                     Actual  %_of_Tot
-------------------------------------------
TOTAL UDP Pkts Received   2995612    100.00
Pkt Recv Errors             94435      3.15
Recv Buffer Errors              0      0.00


Tuesday, November 15, 2016

Glenwood Trail Hike

Trail head on U.S. Highway 20 in Furnessville
Glenwood Trail (formerly Ly-co-ki-we Trail) sits in the Indiana Dunes National Lakeshore in Northwest Indiana. Depending upon the route you take, it is anywhere from 3 - 7 miles more or less.

The terrain is mostly flat with the occasional small hill (6 - 10m) here and there. The bulk of the trail is firm sand, as the trail is shared with horses in the summer. Most of the trail is wooded. As my hike took place in November, there were few leaves left which increased visibility, but also allowed in more sound from surrounding highways. There are clearings throughout, and a few spots take you through wetlands. The path itself tends to be from .3 - 1.5m wide, and generally easy to find, even with the deluge of leaves.

NE part of the trail.

Unfortunately, the bulk of the trail tracks U.S. Highway 20 in the beginning and end, and U.S. Highway 12 to the north for much of the walk. This means lots of noise from trucks moving steel and supplies in and out of local steel mills. That was really the only downside, but enough to warrant making this trail a second choice.

Wildlife was for me, not very interesting; perhaps because I grew up around the area. There were brown squirrels, crows, and white-tailed deer. The image below was shot at about 30m away from the deer. There were in fact, two - one is hiding behind the trees to the right of the one in the picture.

Can you find the doe in this picture?
The highway noise notwithstanding, the walk was enjoyable. Being a Tuesday morning, I only ran into one other person on the trail, and the sand helped make for a good workout.

The full route as captured on my phone.


Details:
Starting elevation: 193 ft.
Peak Elevation: 217 ft.
Distance: 10.6 km
Time: 2.5 hours
Weather: Sunny, wind ~ 5 mph, 55 deg F.

Sunday, October 23, 2016

Cowles Bog Hike

Update: I just uploaded the completed video of the hike to YouTube. Check it out:



Cowles Bog was designated a historical site back in 1965 due to it's varied ecology. It sits in the Indiana Dunes National Lakeshore system, between Michigan City, and the Arcelor-Mittal (formerly Bethlehem) steel mill. Hiking Cowles Bog was my second hike for the year. It's a short hike, but has a character all its own. Here's the path:


The full 4.42 mile hike

I started out in the lower right corner on Highway 12. The initial southwest and westbound walk is a service road, and not too interesting. This part of the hike is done under the shadow of the steel mill, about which I was not enthusiastic. The trees through the remainder of the northwest part of the hike did well at hiding the mill (though there was a scent of coal smoke in the air). Just before hitting the beach there is a sharp incline of about 100', followed by the corresponding descent. Then there is a nice walk in the dunes along Lake Michigan.

A look north out over Lake Michigan

Next, stood the second incline, looming over you, daring you try. Another 100', so the ascent was not too bad, but it was sharp, and the soft beach sand all the way up made for a tough climb. Every step lost about 3 - 4" as you foot slid back down in the sand.

The second incline back into the woods, taunting you at every step.

At the top, there is a nice spot to sit and look out over the lake. If you look out on a clear day at roughly 305 degrees, you can see Chicago on the other side.

The next part of the hike is very woody, and was both quiet and nice. Once through the woods, there is a long trek along the side of the bog:

The south bog.

An interesting plant growing on the bog. I haven't been able to identify it. Leave a comment if you know?


This take you back to the ranger station on Mineral Springs Road. A quick jaunt down the road, and you're done.

The elevation profile.

Details:
Starting elevation: 618 ft.
Peak Elevation: 704 ft.
Distance: 4.42 mi.
Time: 2.0 hours
Weather: Sunny, wind ~ 15 mph, 70 deg F.

Sunday, October 9, 2016

Bald Mountain Hike


This was my first hike. I've documented it for posterity, and hoping there will be more. It took place during a company outing to Park City, UT on October 1st, 2016. Here's the overall route:

The full route starting at St. Regis on the left, ending at Stein-Erickson.

We started up the mountain behind the lodge I was staying in (the company had two; St Regis, and Stein-Erickson). We took switchbacks up the side for about an hour to get to the top. That was fun, though my heart was really pumping. The starting elevation was about 7400 ft., so there wasn’t as much oxygen as I was used to. At the top, most of us decided to go further. One of the guides took about a fourth of the group down, and the rest of us went around, and eventually ended up at Stein-Erickson. 

That's when the real hike began. Nichols, an Australian co-worker asked where a particular service road went. When the guide said it went up to the top of the next mountain, we had already decided to keep pushing. This time, there were only six of us, plus the last guide; a stocky dark-skinned guy with short slightly graying hair, and a white polo. The hikers included Nichols, Wesley, Westin, Jared (one of the Linux guys on my team), and Nicolette, our compliance attorney. We started up the road which became very steep, very fast. It took us through the woods until we came to a clearing; it turned out to be a ski slope. At that point, the guide had to get back to meet up with another group. We went straight up the slope until we hit the trail, maybe 150 feet or so. It doesn’t seem like much, but the grade made for a grueling climb. Once we hit the trail, I started to get very tired, and started to lag behind a bit. Nevertheless, I kept pushing. After another 1000 feet more or less, my fingers started to swell, and started getting numb at the tips. That’s when I had to stop and rest. It took maybe 5 or 10 minutes to get rid of the light-headedness and tingling, so we pushed on. The remainder of the climb, up to about the last 500 feet was much of the same; light-head, tingling, swelling fingers, and nausea started to set in. Wesley, one of the traders hung behind the rest of the group; I suspect it was to help keep an eye on me (I was the oldest of the team, and it was showing). We finally found a service road which then turned and led straight to the top. The walking path continued around the back of the mountain.

We decided to head straight up the service road. This was where the hike got really hard. It was so steep I could only go 30-50 feet before I had to stop and rest for three to five minutes. It went on like that for seven or eight cycles, until the grade started to get more even (still ascending, to be sure, just at a much more tolerable angle). I went around, climbed up a short embankment, then the last path to the summit. I was so hot and tired, I could hardly move. I thought when I got to the top that had I known further down what laid ahead, I would have quit, believing I could not do it, but I did. It was the most demanding physical activity I have ever done, and I loved it.

Elevation Profile


Details:
Starting elevation: 7440 ft.
Peak Elevation: 9344 ft.
Distance: 5.94 mi.
Time: 2.5 hours
Weather: Partly cloudy, wind ~ 10 mph, 70 deg F.

From left to right: Brian (joined up at the top), Nicolette, Nichols, Wesley, Jared, Westin, Rich (front row)